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-2004: Amon Ott <ao@rsbac.org> */
00008 /*                                                   */
00009 /* Last modified: 27/Apr/2004                        */
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   {
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     /* if user role, then deny */
00085     if (i_attr_val1.system_role == SR_user)
00086       return(-EPERM);
00087 #endif
00088 
00089     /* Get jail_id for this process */
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       { /* this process is already in a jail -> limit ip and flags */
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         /* Set current user space to kernel space, because sys_chdir() takes name */
00150         /* from user space */
00151         oldfs = get_fs();
00152         set_fs(KERNEL_DS);
00153         err = sys_chdir("/");
00154         /* Set current user space back to user space */
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     /* Set jail_id for this process */
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     /* Set jail_ip for this process */
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     /* Set jail_flags for this process */
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     /* Set jail_max_caps for this process */
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 /* end of rsbac/adf/jail/syscalls.c */

Generated on Fri Jun 17 09:45:19 2005 for RSBAC by  doxygen 1.4.2