/linux-2.6.21.1-rsbac-1.3.4/rsbac/adf/jail/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-2007: Amon Ott <ao@rsbac.org> */
00008 /*                                                   */
00009 /* Last modified: 29/Jan/2007                        */
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 /*           Global Variables                      */
00033 /************************************************* */
00034 
00035 static rsbac_jail_id_t next_id = 1;
00036 
00037 /************************************************* */
00038 /*          Internal Help functions                */
00039 /************************************************* */
00040 
00041 /************************************************* */
00042 /*          Externally visible functions           */
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 /* Create a jail for current process */
00051 /* Note: It is allowed to create jails within jails, but with restrictions */
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     /* Get jail_id for this process */
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       { /* this process is already in a jail -> limit ip and flags */
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     /* check syslog id */
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         /* Set current user space to kernel space, because sys_chdir() takes name */
00170         /* from user space */
00171         oldfs = get_fs();
00172         set_fs(KERNEL_DS);
00173         err = sys_chdir("/");
00174         /* Set current user space back to user space */
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     /* Set jail_id for this process */
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     /* Set jail_parent for this process */
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     /* Set jail_ip for this process */
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     /* Set jail_flags for this process */
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     /* Set jail_max_caps for this process */
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     /* Set jail_scd_get for this process */
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     /* Set jail_scd_modify for this process */
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 /* end of rsbac/adf/jail/syscalls.c */

Generated on Wed May 16 11:53:32 2007 for RSBAC by  doxygen 1.5.1