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