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 {
00057 union rsbac_target_id_t i_tid;
00058 union rsbac_attribute_value_t i_attr_val1;
00059 int err = 0;
00060 int chk_addr_ret;
00061
00062 if(version != RSBAC_JAIL_VERSION)
00063 return -RSBAC_EINVALIDVERSION;
00064 chk_addr_ret = inet_addr_type(ip);
00065 if (ip != INADDR_ANY &&
00066 chk_addr_ret != RTN_LOCAL &&
00067 chk_addr_ret != RTN_MULTICAST &&
00068 chk_addr_ret != RTN_BROADCAST)
00069 return -EADDRNOTAVAIL;
00070
00071 #if 0
00072 err = rsbac_get_owner(&i_tid.user);
00073 if(err)
00074 return err;
00075 if (rsbac_get_attr(JAIL,
00076 T_USER,
00077 i_tid,
00078 A_jail_role,
00079 &i_attr_val1,
00080 TRUE))
00081 {
00082 rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_role);
00083 }
00084
00085 if (i_attr_val1.system_role == SR_user)
00086 return(-EPERM);
00087 #endif
00088
00089
00090 i_tid.process = current->pid;
00091 if (rsbac_get_attr(JAIL,
00092 T_PROCESS,
00093 i_tid,
00094 A_jail_id,
00095 &i_attr_val1,
00096 TRUE))
00097 {
00098 rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_id);
00099 return(-RSBAC_EREADFAILED);
00100 }
00101 if(i_attr_val1.jail_id)
00102 {
00103 if (rsbac_get_attr(JAIL,
00104 T_PROCESS,
00105 i_tid,
00106 A_jail_flags,
00107 &i_attr_val1,
00108 TRUE))
00109 {
00110 rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_flags);
00111 return(-RSBAC_EREADFAILED);
00112 }
00113 flags &= i_attr_val1.jail_flags;
00114 if (rsbac_get_attr(JAIL,
00115 T_PROCESS,
00116 i_tid,
00117 A_jail_ip,
00118 &i_attr_val1,
00119 TRUE))
00120 {
00121 rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_ip);
00122 return(-RSBAC_EREADFAILED);
00123 }
00124 if(i_attr_val1.jail_ip)
00125 ip = i_attr_val1.jail_ip;
00126 if (rsbac_get_attr(JAIL,
00127 T_PROCESS,
00128 i_tid,
00129 A_jail_max_caps,
00130 &i_attr_val1,
00131 TRUE))
00132 {
00133 rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_max_caps);
00134 return(-RSBAC_EREADFAILED);
00135 }
00136 max_caps &= i_attr_val1.jail_max_caps;
00137 }
00138
00139 if(path)
00140 {
00141 mm_segment_t oldfs;
00142 struct file * file;
00143 struct files_struct *files = current->files;
00144 int fd;
00145
00146 err = sys_chroot(path);
00147 if(err)
00148 return err;
00149
00150
00151 oldfs = get_fs();
00152 set_fs(KERNEL_DS);
00153 err = sys_chdir("/");
00154
00155 set_fs(oldfs);
00156
00157 restart:
00158 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
00159 spin_lock(&files->file_lock);
00160 #else
00161 read_lock(&files->file_lock);
00162 #endif
00163 for(fd=0; fd < files->max_fds; fd++)
00164 {
00165 file = files->fd[fd];
00166 if( file
00167 && file->f_dentry
00168 && file->f_dentry->d_inode
00169 && S_ISDIR(file->f_dentry->d_inode->i_mode)
00170 )
00171 {
00172 char * filename;
00173
00174 #ifdef CONFIG_RSBAC_LOG_FULL_PATH
00175 filename = rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + 4);
00176 if(filename)
00177 rsbac_get_full_path(file->f_dentry, filename, CONFIG_RSBAC_MAX_PATH_LEN);
00178 #else
00179 filename = rsbac_kmalloc(RSBAC_MAXNAMELEN + 4);
00180 if(filename)
00181 rsbac_get_full_path(file->f_dentry, filename, RSBAC_MAXNAMELEN);
00182 #endif
00183
00184 #ifdef CONFIG_RSBAC_RMSG
00185 rsbac_printk(KERN_INFO
00186 "rsbac_jail_sys_jail(): avoid possible chroot breakout by closing open dir fd %u, inode %u, device %02u:%02u, path %s\n",
00187 fd,
00188 file->f_dentry->d_inode->i_ino,
00189 MAJOR(file->f_dentry->d_sb->s_dev),
00190 MINOR(file->f_dentry->d_sb->s_dev),
00191 filename);
00192 #endif
00193 #ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
00194 if (!rsbac_nosyslog)
00195 #endif
00196 printk(KERN_INFO
00197 "rsbac_jail_sys_jail(): avoid possible chroot breakout by closing open dir fd %u, inode %lu, device %02u:%02u, path %s\n",
00198 fd,
00199 file->f_dentry->d_inode->i_ino,
00200 MAJOR(file->f_dentry->d_sb->s_dev),
00201 MINOR(file->f_dentry->d_sb->s_dev),
00202 filename);
00203 if(filename)
00204 rsbac_kfree(filename);
00205
00206 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
00207 spin_unlock(&files->file_lock);
00208 #else
00209 read_unlock(&files->file_lock);
00210 #endif
00211 sys_close(fd);
00212 goto restart;
00213 }
00214 }
00215 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
00216 spin_unlock(&files->file_lock);
00217 #else
00218 read_unlock(&files->file_lock);
00219 #endif
00220 }
00221
00222
00223 i_attr_val1.jail_id = next_id++;
00224 if (rsbac_set_attr(JAIL,
00225 T_PROCESS,
00226 i_tid,
00227 A_jail_id,
00228 i_attr_val1))
00229 {
00230 rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_id);
00231 return(-RSBAC_EWRITEFAILED);
00232 }
00233
00234 i_attr_val1.jail_ip = ip;
00235 if (rsbac_set_attr(JAIL,
00236 T_PROCESS,
00237 i_tid,
00238 A_jail_ip,
00239 i_attr_val1))
00240 {
00241 rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_ip);
00242 return(-RSBAC_EWRITEFAILED);
00243 }
00244
00245 i_attr_val1.jail_flags = flags;
00246 if (rsbac_set_attr(JAIL,
00247 T_PROCESS,
00248 i_tid,
00249 A_jail_flags,
00250 i_attr_val1))
00251 {
00252 rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_flags);
00253 return(-RSBAC_EWRITEFAILED);
00254 }
00255
00256 i_attr_val1.jail_max_caps = max_caps;
00257 if (rsbac_set_attr(JAIL,
00258 T_PROCESS,
00259 i_tid,
00260 A_jail_max_caps,
00261 i_attr_val1))
00262 {
00263 rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_flags);
00264 return(-RSBAC_EWRITEFAILED);
00265 }
00266 return err;
00267 }
00268
00269