jail_syscalls.c

Go to the documentation of this file.
00001 /*************************************************** */
00002 /* Rule Set Based Access Control                     */
00003 /* Implementation of the Access Control Decision     */
00004 /* Facility (ADF) - JAIL module                      */
00005 /* File: rsbac/adf/jail/syscalls.c                   */
00006 /*                                                   */
00007 /* Author and (c) 1999-2005: Amon Ott <ao@rsbac.org> */
00008 /*                                                   */
00009 /* Last modified: 02/Aug/2005                        */
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 /*           Global Variables                      */
00032 /************************************************* */
00033 
00034 static rsbac_jail_id_t next_id = 1;
00035 
00036 /************************************************* */
00037 /*          Internal Help functions                */
00038 /************************************************* */
00039 
00040 /************************************************* */
00041 /*          Externally visible functions           */
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 /* Create a jail for current process */
00050 /* Note: It is allowed to create jails within jails, but with restrictions */
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     /* Get jail_id for this process */
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       { /* this process is already in a jail -> limit ip and flags */
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         /* Set current user space to kernel space, because sys_chdir() takes name */
00159         /* from user space */
00160         oldfs = get_fs();
00161         set_fs(KERNEL_DS);
00162         err = sys_chdir("/");
00163         /* Set current user space back to user space */
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     /* Set jail_id for this process */
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     /* Set jail_ip for this process */
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     /* Set jail_flags for this process */
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     /* Set jail_max_caps for this process */
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     /* Set jail_scd_get for this process */
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     /* Set jail_scd_modify for this process */
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 /* end of rsbac/adf/jail/syscalls.c */

Generated on Sun May 21 14:30:50 2006 for RSBAC by  doxygen 1.4.2