00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <linux/string.h>
00013 #include <linux/sched.h>
00014 #include <linux/errno.h>
00015 #include <linux/version.h>
00016 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
00017 #include <linux/syscalls.h>
00018 #include <linux/file.h>
00019 #endif
00020 #include <rsbac/types.h>
00021 #include <rsbac/aci.h>
00022 #include <rsbac/error.h>
00023 #include <rsbac/rkmem.h>
00024 #include <rsbac/debug.h>
00025 #include <rsbac/helpers.h>
00026 #include <rsbac/getname.h>
00027 #include <rsbac/network.h>
00028 #include <asm/uaccess.h>
00029
00030
00031
00032
00033
00034 static rsbac_jail_id_t next_id = 1;
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
00045 extern long sys_chroot(const char * filename);
00046 extern long sys_chdir(const char * filename);
00047 #endif
00048
00049
00050
00051 int rsbac_jail_sys_jail(rsbac_version_t version,
00052 char * path,
00053 rsbac_jail_ip_t ip,
00054 rsbac_jail_flags_t flags,
00055 rsbac_cap_vector_t max_caps,
00056 rsbac_jail_scd_vector_t scd_get,
00057 rsbac_jail_scd_vector_t scd_modify)
00058 {
00059 union rsbac_target_id_t i_tid;
00060 union rsbac_attribute_value_t i_attr_val1;
00061 int err = 0;
00062 int chk_addr_ret;
00063
00064 if(version != RSBAC_JAIL_VERSION)
00065 return -RSBAC_EINVALIDVERSION;
00066 chk_addr_ret = inet_addr_type(ip);
00067 if (ip != INADDR_ANY &&
00068 chk_addr_ret != RTN_LOCAL &&
00069 chk_addr_ret != RTN_MULTICAST &&
00070 chk_addr_ret != RTN_BROADCAST)
00071 return -EADDRNOTAVAIL;
00072
00073
00074 i_tid.process = current->pid;
00075 if (rsbac_get_attr(JAIL,
00076 T_PROCESS,
00077 i_tid,
00078 A_jail_id,
00079 &i_attr_val1,
00080 TRUE))
00081 {
00082 rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_id);
00083 return(-RSBAC_EREADFAILED);
00084 }
00085 if(i_attr_val1.jail_id)
00086 {
00087 if (rsbac_get_attr(JAIL,
00088 T_PROCESS,
00089 i_tid,
00090 A_jail_flags,
00091 &i_attr_val1,
00092 TRUE))
00093 {
00094 rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_flags);
00095 return(-RSBAC_EREADFAILED);
00096 }
00097 flags &= i_attr_val1.jail_flags;
00098 if (rsbac_get_attr(JAIL,
00099 T_PROCESS,
00100 i_tid,
00101 A_jail_scd_get,
00102 &i_attr_val1,
00103 TRUE))
00104 {
00105 rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_scd_get);
00106 return(-RSBAC_EREADFAILED);
00107 }
00108 scd_get &= i_attr_val1.jail_scd_get;
00109 if (rsbac_get_attr(JAIL,
00110 T_PROCESS,
00111 i_tid,
00112 A_jail_scd_modify,
00113 &i_attr_val1,
00114 TRUE))
00115 {
00116 rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_scd_modify);
00117 return(-RSBAC_EREADFAILED);
00118 }
00119 scd_modify &= i_attr_val1.jail_scd_modify;
00120 if (rsbac_get_attr(JAIL,
00121 T_PROCESS,
00122 i_tid,
00123 A_jail_ip,
00124 &i_attr_val1,
00125 TRUE))
00126 {
00127 rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_ip);
00128 return(-RSBAC_EREADFAILED);
00129 }
00130 if(i_attr_val1.jail_ip)
00131 ip = i_attr_val1.jail_ip;
00132 if (rsbac_get_attr(JAIL,
00133 T_PROCESS,
00134 i_tid,
00135 A_jail_max_caps,
00136 &i_attr_val1,
00137 TRUE))
00138 {
00139 rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_max_caps);
00140 return(-RSBAC_EREADFAILED);
00141 }
00142 max_caps &= i_attr_val1.jail_max_caps;
00143 }
00144
00145 if(path)
00146 {
00147 mm_segment_t oldfs;
00148 struct file * file;
00149 struct files_struct *files = current->files;
00150 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
00151 struct fdtable *fdt;
00152 #endif
00153 int fd;
00154
00155 err = sys_chroot(path);
00156 if(err)
00157 return err;
00158
00159
00160 oldfs = get_fs();
00161 set_fs(KERNEL_DS);
00162 err = sys_chdir("/");
00163
00164 set_fs(oldfs);
00165
00166 restart:
00167 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
00168 rcu_read_lock();
00169 fdt = files_fdtable(files);
00170 for(fd=0; fd < fdt->max_fds; fd++)
00171 {
00172 file = fcheck(fd);
00173 #else
00174 read_lock(&files->file_lock);
00175 for(fd=0; fd < files->max_fds; fd++)
00176 {
00177 file = files->fd[fd];
00178 #endif
00179 if( file
00180 && file->f_dentry
00181 && file->f_dentry->d_inode
00182 && S_ISDIR(file->f_dentry->d_inode->i_mode)
00183 )
00184 {
00185 char * filename;
00186
00187 #ifdef CONFIG_RSBAC_LOG_FULL_PATH
00188 filename = rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + 4);
00189 if(filename)
00190 rsbac_get_full_path(file->f_dentry, filename, CONFIG_RSBAC_MAX_PATH_LEN);
00191 #else
00192 filename = rsbac_kmalloc(RSBAC_MAXNAMELEN + 4);
00193 if(filename)
00194 rsbac_get_full_path(file->f_dentry, filename, RSBAC_MAXNAMELEN);
00195 #endif
00196
00197 rsbac_printk(KERN_INFO
00198 "rsbac_jail_sys_jail(): avoid possible chroot breakout by closing open dir fd %u, inode %u, device %02u:%02u, path %s\n",
00199 fd,
00200 file->f_dentry->d_inode->i_ino,
00201 MAJOR(file->f_dentry->d_sb->s_dev),
00202 MINOR(file->f_dentry->d_sb->s_dev),
00203 filename);
00204 if(filename)
00205 rsbac_kfree(filename);
00206
00207 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
00208 rcu_read_unlock();
00209 #else
00210 read_unlock(&files->file_lock);
00211 #endif
00212 sys_close(fd);
00213 goto restart;
00214 }
00215 }
00216 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
00217 rcu_read_unlock();
00218 #else
00219 read_unlock(&files->file_lock);
00220 #endif
00221 }
00222
00223
00224 i_attr_val1.jail_id = next_id++;
00225 if (rsbac_set_attr(JAIL,
00226 T_PROCESS,
00227 i_tid,
00228 A_jail_id,
00229 i_attr_val1))
00230 {
00231 rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_id);
00232 return(-RSBAC_EWRITEFAILED);
00233 }
00234
00235 i_attr_val1.jail_ip = ip;
00236 if (rsbac_set_attr(JAIL,
00237 T_PROCESS,
00238 i_tid,
00239 A_jail_ip,
00240 i_attr_val1))
00241 {
00242 rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_ip);
00243 return(-RSBAC_EWRITEFAILED);
00244 }
00245
00246 i_attr_val1.jail_flags = flags;
00247 if (rsbac_set_attr(JAIL,
00248 T_PROCESS,
00249 i_tid,
00250 A_jail_flags,
00251 i_attr_val1))
00252 {
00253 rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_flags);
00254 return(-RSBAC_EWRITEFAILED);
00255 }
00256
00257 i_attr_val1.jail_max_caps = max_caps;
00258 if (rsbac_set_attr(JAIL,
00259 T_PROCESS,
00260 i_tid,
00261 A_jail_max_caps,
00262 i_attr_val1))
00263 {
00264 rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_max_caps);
00265 return(-RSBAC_EWRITEFAILED);
00266 }
00267
00268 i_attr_val1.jail_scd_get = scd_get;
00269 if (rsbac_set_attr(JAIL,
00270 T_PROCESS,
00271 i_tid,
00272 A_jail_scd_get,
00273 i_attr_val1))
00274 {
00275 rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_scd_get);
00276 return(-RSBAC_EWRITEFAILED);
00277 }
00278
00279 i_attr_val1.jail_scd_modify = scd_modify;
00280 if (rsbac_set_attr(JAIL,
00281 T_PROCESS,
00282 i_tid,
00283 A_jail_scd_modify,
00284 i_attr_val1))
00285 {
00286 rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_scd_modify);
00287 return(-RSBAC_EWRITEFAILED);
00288 }
00289 return err;
00290 }
00291
00292