Commit 3afa49eb authored by Stephen D. Smalley's avatar Stephen D. Smalley Committed by Linus Torvalds

[PATCH] 2.5.52-lsm-{dummy,ipc}.patch

This patch adds the remaining System V IPC hooks, including the inline
documentation for them in security.h.  This includes a restored
sem_semop hook, as it does seem to be necessary to support fine-grained
access.

All of these System V IPC hooks are used by SELinux.  The SELinux System
V IPC access controls were originally described in the technical report
available from http://www.nsa.gov/selinux/slinux-abs.html, and the
LSM-based implementation is described in the technical report available
from http://www.nsa.gov/selinux/module-abs.html.
parent 60e7fd5e
......@@ -69,6 +69,7 @@ struct msg_msg {
long m_type;
int m_ts; /* message text size */
struct msg_msgseg* next;
void *security;
/* the actual message follows immediately */
};
......
This diff is collapsed.
......@@ -132,6 +132,9 @@ static int newque (key_t key, int msgflg)
static void free_msg(struct msg_msg* msg)
{
struct msg_msgseg* seg;
security_msg_msg_free(msg);
seg = msg->next;
kfree(msg);
while(seg != NULL) {
......@@ -157,6 +160,7 @@ static struct msg_msg* load_msg(void* src, int len)
return ERR_PTR(-ENOMEM);
msg->next = NULL;
msg->security = NULL;
if (copy_from_user(msg+1, src, alen)) {
err = -EFAULT;
......@@ -186,6 +190,11 @@ static struct msg_msg* load_msg(void* src, int len)
len -= alen;
src = ((char*)src)+alen;
}
err = security_msg_msg_alloc(msg);
if (err)
goto out_err;
return msg;
out_err:
......@@ -308,8 +317,12 @@ asmlinkage long sys_msgget (key_t key, int msgflg)
BUG();
if (ipcperms(&msq->q_perm, msgflg))
ret = -EACCES;
else
ret = msg_buildid(id, msq->q_perm.seq);
else {
int qid = msg_buildid(id, msq->q_perm.seq);
ret = security_msg_queue_associate(msq, msgflg);
if (!ret)
ret = qid;
}
msg_unlock(msq);
}
up(&msg_ids.sem);
......@@ -431,6 +444,11 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
* due to padding, it's not enough
* to set all member fields.
*/
err = security_msg_queue_msgctl(NULL, cmd);
if (err)
return err;
memset(&msginfo,0,sizeof(msginfo));
msginfo.msgmni = msg_ctlmni;
msginfo.msgmax = msg_ctlmax;
......@@ -481,6 +499,10 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
if (ipcperms (&msq->q_perm, S_IRUGO))
goto out_unlock;
err = security_msg_queue_msgctl(msq, cmd);
if (err)
goto out_unlock;
kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm);
tbuf.msg_stime = msq->q_stime;
tbuf.msg_rtime = msq->q_rtime;
......@@ -523,11 +545,16 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
/* We _could_ check for CAP_CHOWN above, but we don't */
goto out_unlock_up;
err = security_msg_queue_msgctl(msq, cmd);
if (err)
goto out_unlock_up;
switch (cmd) {
case IPC_SET:
{
if (setbuf.qbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
goto out_unlock_up;
msq->q_qbytes = setbuf.qbytes;
ipcp->uid = setbuf.uid;
......@@ -593,7 +620,8 @@ static inline int pipelined_send(struct msg_queue* msq, struct msg_msg* msg)
struct msg_receiver* msr;
msr = list_entry(tmp,struct msg_receiver,r_list);
tmp = tmp->next;
if(testmsg(msg,msr->r_msgtype,msr->r_mode)) {
if(testmsg(msg,msr->r_msgtype,msr->r_mode) &&
!security_msg_queue_msgrcv(msq, msg, msr->r_tsk, msr->r_msgtype, msr->r_mode)) {
list_del(&msr->r_list);
if(msr->r_maxsize < msg->m_ts) {
msr->r_msg = ERR_PTR(-E2BIG);
......@@ -644,6 +672,10 @@ asmlinkage long sys_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int ms
if (ipcperms(&msq->q_perm, S_IWUGO))
goto out_unlock_free;
err = security_msg_queue_msgsnd(msq, msg, msgflg);
if (err)
goto out_unlock_free;
if(msgsz + msq->q_cbytes > msq->q_qbytes ||
1 + msq->q_qnum > msq->q_qbytes) {
struct msg_sender s;
......@@ -742,7 +774,8 @@ asmlinkage long sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz,
found_msg=NULL;
while (tmp != &msq->q_messages) {
msg = list_entry(tmp,struct msg_msg,m_list);
if(testmsg(msg,msgtyp,mode)) {
if(testmsg(msg,msgtyp,mode) &&
!security_msg_queue_msgrcv(msq, msg, current, msgtyp, mode)) {
found_msg = msg;
if(mode == SEARCH_LESSEQUAL && msg->m_type != 1) {
found_msg=msg;
......
......@@ -188,8 +188,12 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
err = -EINVAL;
else if (ipcperms(&sma->sem_perm, semflg))
err = -EACCES;
else
err = sem_buildid(id, sma->sem_perm.seq);
else {
int semid = sem_buildid(id, sma->sem_perm.seq);
err = security_sem_associate(sma, semflg);
if (!err)
err = semid;
}
sem_unlock(sma);
}
......@@ -466,6 +470,10 @@ static int semctl_nolock(int semid, int semnum, int cmd, int version, union semu
struct seminfo seminfo;
int max_id;
err = security_sem_semctl(NULL, cmd);
if (err)
return err;
memset(&seminfo,0,sizeof(seminfo));
seminfo.semmni = sc_semmni;
seminfo.semmns = sc_semmns;
......@@ -506,6 +514,11 @@ static int semctl_nolock(int semid, int semnum, int cmd, int version, union semu
err = -EACCES;
if (ipcperms (&sma->sem_perm, S_IRUGO))
goto out_unlock;
err = security_sem_semctl(sma, cmd);
if (err)
goto out_unlock;
id = sem_buildid(semid, sma->sem_perm.seq);
kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm);
......@@ -549,6 +562,11 @@ static int semctl_main(int semid, int semnum, int cmd, int version, union semun
if (ipcperms (&sma->sem_perm, (cmd==SETVAL||cmd==SETALL)?S_IWUGO:S_IRUGO))
goto out_unlock;
err = security_sem_semctl(sma, cmd);
if (err)
goto out_unlock;
err = -EACCES;
switch (cmd) {
case GETALL:
{
......@@ -740,6 +758,10 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
goto out_unlock;
}
err = security_sem_semctl(sma, cmd);
if (err)
goto out_unlock;
switch(cmd){
case IPC_RMID:
freeary(semid);
......@@ -1035,6 +1057,12 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf *tsops,
error = -EACCES;
if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
goto out_unlock_semundo_free;
error = security_sem_semop(sma, sops, nsops, alter);
if (error)
goto out_unlock_semundo_free;
error = -EACCES;
if (undos) {
/* Make sure we have an undo structure
* for this process and this semaphore set.
......
......@@ -257,8 +257,12 @@ asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
err = -EINVAL;
else if (ipcperms(&shp->shm_perm, shmflg))
err = -EACCES;
else
err = shm_buildid(id, shp->shm_perm.seq);
else {
int shmid = shm_buildid(id, shp->shm_perm.seq);
err = security_shm_associate(shp, shmflg);
if (!err)
err = shmid;
}
shm_unlock(shp);
}
up(&shm_ids.sem);
......@@ -399,6 +403,10 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
{
struct shminfo64 shminfo;
err = security_shm_shmctl(NULL, cmd);
if (err)
return err;
memset(&shminfo,0,sizeof(shminfo));
shminfo.shmmni = shminfo.shmseg = shm_ctlmni;
shminfo.shmmax = shm_ctlmax;
......@@ -417,6 +425,10 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
{
struct shm_info shm_info;
err = security_shm_shmctl(NULL, cmd);
if (err)
return err;
memset(&shm_info,0,sizeof(shm_info));
down(&shm_ids.sem);
shm_info.used_ids = shm_ids.in_use;
......@@ -458,6 +470,9 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
err=-EACCES;
if (ipcperms (&shp->shm_perm, S_IRUGO))
goto out_unlock;
err = security_shm_shmctl(shp, cmd);
if (err)
goto out_unlock;
kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm);
tbuf.shm_segsz = shp->shm_segsz;
tbuf.shm_atime = shp->shm_atim;
......@@ -495,6 +510,11 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
err = shm_checkid(shp,shmid);
if(err)
goto out_unlock;
err = security_shm_shmctl(shp, cmd);
if (err)
goto out_unlock;
if(cmd==SHM_LOCK) {
if (!is_file_hugepages(shp->shm_file))
shmem_lock(shp->shm_file, 1);
......@@ -527,12 +547,18 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
err = shm_checkid(shp, shmid);
if(err)
goto out_unlock_up;
if (current->euid != shp->shm_perm.uid &&
current->euid != shp->shm_perm.cuid &&
!capable(CAP_SYS_ADMIN)) {
err=-EPERM;
goto out_unlock_up;
}
err = security_shm_shmctl(shp, cmd);
if (err)
goto out_unlock_up;
if (shp->shm_nattch){
shp->shm_flags |= SHM_DEST;
/* Do not find it any more */
......@@ -565,6 +591,10 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
goto out_unlock_up;
}
err = security_shm_shmctl(shp, cmd);
if (err)
goto out_unlock_up;
shp->shm_perm.uid = setbuf.uid;
shp->shm_perm.gid = setbuf.gid;
shp->shm_flags = (shp->shm_flags & ~S_IRWXUGO)
......@@ -653,6 +683,13 @@ asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
err = -EACCES;
goto out;
}
err = security_shm_shmat(shp, shmaddr, shmflg);
if (err) {
shm_unlock(shp);
return err;
}
file = shp->shm_file;
size = file->f_dentry->d_inode->i_size;
shp->shm_nattch++;
......
......@@ -501,6 +501,15 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
return 0;
}
static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
{
return 0;
}
static void dummy_msg_msg_free_security (struct msg_msg *msg)
{
return;
}
static int dummy_msg_queue_alloc_security (struct msg_queue *msq)
{
......@@ -512,6 +521,30 @@ static void dummy_msg_queue_free_security (struct msg_queue *msq)
return;
}
static int dummy_msg_queue_associate (struct msg_queue *msq,
int msqflg)
{
return 0;
}
static int dummy_msg_queue_msgctl (struct msg_queue *msq, int cmd)
{
return 0;
}
static int dummy_msg_queue_msgsnd (struct msg_queue *msq, struct msg_msg *msg,
int msgflg)
{
return 0;
}
static int dummy_msg_queue_msgrcv (struct msg_queue *msq, struct msg_msg *msg,
struct task_struct *target, long type,
int mode)
{
return 0;
}
static int dummy_shm_alloc_security (struct shmid_kernel *shp)
{
return 0;
......@@ -522,6 +555,22 @@ static void dummy_shm_free_security (struct shmid_kernel *shp)
return;
}
static int dummy_shm_associate (struct shmid_kernel *shp, int shmflg)
{
return 0;
}
static int dummy_shm_shmctl (struct shmid_kernel *shp, int cmd)
{
return 0;
}
static int dummy_shm_shmat (struct shmid_kernel *shp, char *shmaddr,
int shmflg)
{
return 0;
}
static int dummy_sem_alloc_security (struct sem_array *sma)
{
return 0;
......@@ -532,6 +581,22 @@ static void dummy_sem_free_security (struct sem_array *sma)
return;
}
static int dummy_sem_associate (struct sem_array *sma, int semflg)
{
return 0;
}
static int dummy_sem_semctl (struct sem_array *sma, int cmd)
{
return 0;
}
static int dummy_sem_semop (struct sem_array *sma,
struct sembuf *sops, unsigned nsops, int alter)
{
return 0;
}
static int dummy_register_security (const char *name, struct security_operations *ops)
{
return -EINVAL;
......@@ -640,12 +705,24 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, task_kmod_set_label);
set_to_dummy_if_null(ops, task_reparent_to_init);
set_to_dummy_if_null(ops, ipc_permission);
set_to_dummy_if_null(ops, msg_msg_alloc_security);
set_to_dummy_if_null(ops, msg_msg_free_security);
set_to_dummy_if_null(ops, msg_queue_alloc_security);
set_to_dummy_if_null(ops, msg_queue_free_security);
set_to_dummy_if_null(ops, msg_queue_associate);
set_to_dummy_if_null(ops, msg_queue_msgctl);
set_to_dummy_if_null(ops, msg_queue_msgsnd);
set_to_dummy_if_null(ops, msg_queue_msgrcv);
set_to_dummy_if_null(ops, shm_alloc_security);
set_to_dummy_if_null(ops, shm_free_security);
set_to_dummy_if_null(ops, shm_associate);
set_to_dummy_if_null(ops, shm_shmctl);
set_to_dummy_if_null(ops, shm_shmat);
set_to_dummy_if_null(ops, sem_alloc_security);
set_to_dummy_if_null(ops, sem_free_security);
set_to_dummy_if_null(ops, sem_associate);
set_to_dummy_if_null(ops, sem_semctl);
set_to_dummy_if_null(ops, sem_semop);
set_to_dummy_if_null(ops, register_security);
set_to_dummy_if_null(ops, unregister_security);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment