X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=ipc%2Fshm.c;h=8098968519026406191014b4cb64ee870e2a721c;hb=8b8c8d280ab2d18fe6e42d671f60d4ffed451cdc;hp=9162123a7b23c348aca8669c56ea56bfbeacadb6;hpb=fab8d6ddf6dee2608869005d45fe97f70e4f5bdd;p=linux-2.6-omap-h63xx.git diff --git a/ipc/shm.c b/ipc/shm.c index 9162123a7b2..80989685190 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -13,6 +13,8 @@ * Shared /dev/zero support, Kanoj Sarcar * Move the mm functionality over to mm/shmem.c, Christoph Rohland * + * support for audit of ipc object properties and permission changes + * Dustin Kirkland */ #include @@ -30,6 +32,7 @@ #include #include #include +#include #include @@ -90,8 +93,8 @@ static inline int shm_addid(struct shmid_kernel *shp) static inline void shm_inc (int id) { struct shmid_kernel *shp; - if(!(shp = shm_lock(id))) - BUG(); + shp = shm_lock(id); + BUG_ON(!shp); shp->shm_atim = get_seconds(); shp->shm_lprid = current->tgid; shp->shm_nattch++; @@ -109,7 +112,7 @@ static void shm_open (struct vm_area_struct *shmd) * * @shp: struct to free * - * It has to be called with shp and shm_ids.sem locked, + * It has to be called with shp and shm_ids.mutex locked, * but returns with shp unlocked and freed. */ static void shm_destroy (struct shmid_kernel *shp) @@ -139,10 +142,10 @@ static void shm_close (struct vm_area_struct *shmd) int id = file->f_dentry->d_inode->i_ino; struct shmid_kernel *shp; - down (&shm_ids.sem); + mutex_lock(&shm_ids.mutex); /* remove from the list of attaches of the shm segment */ - if(!(shp = shm_lock(id))) - BUG(); + shp = shm_lock(id); + BUG_ON(!shp); shp->shm_lprid = current->tgid; shp->shm_dtim = get_seconds(); shp->shm_nattch--; @@ -151,7 +154,7 @@ static void shm_close (struct vm_area_struct *shmd) shm_destroy (shp); else shm_unlock(shp); - up (&shm_ids.sem); + mutex_unlock(&shm_ids.mutex); } static int shm_mmap(struct file * file, struct vm_area_struct * vma) @@ -161,6 +164,8 @@ static int shm_mmap(struct file * file, struct vm_area_struct * vma) ret = shmem_mmap(file, vma); if (ret == 0) { vma->vm_ops = &shm_vm_ops; + if (!(vma->vm_flags & VM_WRITE)) + vma->vm_flags &= ~VM_MAYWRITE; shm_inc(file->f_dentry->d_inode->i_ino); } @@ -270,7 +275,7 @@ asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) struct shmid_kernel *shp; int err, id = 0; - down(&shm_ids.sem); + mutex_lock(&shm_ids.mutex); if (key == IPC_PRIVATE) { err = newseg(key, shmflg, size); } else if ((id = ipc_findkey(&shm_ids, key)) == -1) { @@ -282,8 +287,7 @@ asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) err = -EEXIST; } else { shp = shm_lock(id); - if(shp==NULL) - BUG(); + BUG_ON(shp==NULL); if (shp->shm_segsz < size) err = -EINVAL; else if (ipcperms(&shp->shm_perm, shmflg)) @@ -296,7 +300,7 @@ asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) } shm_unlock(shp); } - up(&shm_ids.sem); + mutex_unlock(&shm_ids.mutex); return err; } @@ -467,14 +471,14 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) return err; memset(&shm_info,0,sizeof(shm_info)); - down(&shm_ids.sem); + mutex_lock(&shm_ids.mutex); shm_info.used_ids = shm_ids.in_use; shm_get_stat (&shm_info.shm_rss, &shm_info.shm_swp); shm_info.shm_tot = shm_tot; shm_info.swap_attempts = 0; shm_info.swap_successes = 0; err = shm_ids.max_id; - up(&shm_ids.sem); + mutex_unlock(&shm_ids.mutex); if(copy_to_user (buf, &shm_info, sizeof(shm_info))) { err = -EFAULT; goto out; @@ -540,6 +544,10 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) if(err) goto out_unlock; + err = audit_ipc_obj(&(shp->shm_perm)); + if (err) + goto out_unlock; + if (!capable(CAP_IPC_LOCK)) { err = -EPERM; if (current->euid != shp->shm_perm.uid && @@ -583,7 +591,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) * Instead we set a destroyed flag, and then blow * the name away when the usage hits zero. */ - down(&shm_ids.sem); + mutex_lock(&shm_ids.mutex); shp = shm_lock(shmid); err = -EINVAL; if (shp == NULL) @@ -592,6 +600,10 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) if(err) goto out_unlock_up; + err = audit_ipc_obj(&(shp->shm_perm)); + if (err) + goto out_unlock_up; + if (current->euid != shp->shm_perm.uid && current->euid != shp->shm_perm.cuid && !capable(CAP_SYS_ADMIN)) { @@ -610,7 +622,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) shm_unlock(shp); } else shm_destroy (shp); - up(&shm_ids.sem); + mutex_unlock(&shm_ids.mutex); goto out; } @@ -620,9 +632,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) err = -EFAULT; goto out; } - if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode))) - return err; - down(&shm_ids.sem); + mutex_lock(&shm_ids.mutex); shp = shm_lock(shmid); err=-EINVAL; if(shp==NULL) @@ -630,6 +640,12 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) err = shm_checkid(shp,shmid); if(err) goto out_unlock_up; + err = audit_ipc_obj(&(shp->shm_perm)); + if (err) + goto out_unlock_up; + err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode, &(shp->shm_perm)); + if (err) + goto out_unlock_up; err=-EPERM; if (current->euid != shp->shm_perm.uid && current->euid != shp->shm_perm.cuid && @@ -658,7 +674,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) out_unlock_up: shm_unlock(shp); out_up: - up(&shm_ids.sem); + mutex_unlock(&shm_ids.mutex); goto out; out_unlock: shm_unlock(shp); @@ -771,16 +787,16 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) invalid: up_write(¤t->mm->mmap_sem); - down (&shm_ids.sem); - if(!(shp = shm_lock(shmid))) - BUG(); + mutex_lock(&shm_ids.mutex); + shp = shm_lock(shmid); + BUG_ON(!shp); shp->shm_nattch--; if(shp->shm_nattch == 0 && shp->shm_perm.mode & SHM_DEST) shm_destroy (shp); else shm_unlock(shp); - up (&shm_ids.sem); + mutex_unlock(&shm_ids.mutex); *raddr = (unsigned long) user_addr; err = 0; @@ -814,6 +830,9 @@ asmlinkage long sys_shmdt(char __user *shmaddr) loff_t size = 0; int retval = -EINVAL; + if (addr & ~PAGE_MASK) + return retval; + down_write(&mm->mmap_sem); /*