Re: 2001_06_20 patch against 2.4.5

From: Stephen Smalley (sdsat_private)
Date: Thu Jun 21 2001 - 12:24:54 PDT

  • Next message: Chris Wright: "Re: 2001_06_20 patch against 2.4.5"

    I've attached a small patch between the latest WireX
    BitKeeper tree and our tree that adds hooks for
    System V IPC message queues (by Chris Vance) and
    for sysctl (by Wayne Salamon).  I'm not sure how
    these should be integrated into the WireX tree -
    2.4.5 or 2.4.6-pre3?
    
    --
    Stephen D. Smalley, NAI Labs
    ssmalleyat_private
    
    
    
    On Wed, 20 Jun 2001, Chris Wright wrote:
    
    > Latest lsm patch is available.
    >     http://lsm.immunix.org/patches/lsm-2001_06_20-2.4.5.patch.gz
    >  
    > BitKeeper has been updated.
    >  
    > This is Stephen Smalley's latest proposal merged into 2.4.5.  I backed
    > out the 2.4.6-pre3 merge.  The relevant changes that happened after that
    > merge are in this patch (and in BitKeeper) against 2.4.5.
    > 
    > Thanks to everyone who helped, either with code or discussion, produce
    > this patch.  I'd especially like to thank Stephen for this solid
    > contribution.  He did a lot of work to unify the hooks and organize
    > the framework.  Both the dummy and capabilities code are effectively 
    > using this newly organized lsm framework
    > 
    > Patch includes:
    >  * capable hook is used as coarse grained permissive hook
    >  * fine grained hooks are restrictive and uniform
    >  * default (dummy) security_ops is usable as superuser check
    >  * capabilities is a module and implements capabilities specific bits of
    >    ptrace, compute_creds, etc.
    >  * base logic for compute_creds is in kernel, the rest is done in
    >    module, this fixed the setuid problem with dummy_ops
    >  * added kmod_set_label and post_set*id hooks
    >  * many hooks had additional parameters to make them more useful
    >  * change to kernel to copy userspace info to tmp variable to use some
    >    of the additional parameters added to hooks
    >  * added IPC and fowner/fcntl/sigiotask updates from Chris Vance
    >    <cvanceat_private>, NAI Labs.
    >  * added ioctl from Wayne Salamon.
    >  * initial port to IA64 from Greg Kroah-Hartman
    >  # secondary module registration now takes a module name as well
    >  * ...and some things that i'm forgetting right now ;-)
    >  
    > -chris
    > 
    > p.s. for those BitKeeper users that want to re-sync without
    > re-cloning...there are probably many ways to do this.  I know of an easy
    > fool proof one. In your local repository, simply undo any changes after 1.73:
    > 
    > bk undo -a1.73
    > bk pull
    > 
    > and you're done.
    > 
    > _______________________________________________
    > linux-security-module mailing list
    > linux-security-moduleat_private
    > http://mail.wirex.com/mailman/listinfo/linux-security-module
    > 
    
    
    diff -X exclude -ur wirex/lsm/include/linux/msg.h lsm/lsm-new/include/linux/msg.h
    --- wirex/lsm/include/linux/msg.h	Mon Jun 18 16:40:03 2001
    +++ lsm/lsm-new/include/linux/msg.h	Thu Jun 21 11:39:49 2001
    @@ -63,6 +63,36 @@
     
     #ifdef __KERNEL__
     
    +/* one msg_msg structure for each message */
    +struct msg_msg {
    +	struct list_head m_list; 
    +	long  m_type;          
    +	int m_ts;           /* message text size */
    +	struct msg_msgseg* next;
    +	void *security;
    +	/* the actual message follows immediately */
    +};
    +
    +#define DATALEN_MSG	(PAGE_SIZE-sizeof(struct msg_msg))
    +#define DATALEN_SEG	(PAGE_SIZE-sizeof(struct msg_msgseg))
    +
    +/* one msq_queue structure for each present queue on the system */
    +struct msg_queue {
    +	struct kern_ipc_perm q_perm;
    +	time_t q_stime;			/* last msgsnd time */
    +	time_t q_rtime;			/* last msgrcv time */
    +	time_t q_ctime;			/* last change time */
    +	unsigned long q_cbytes;		/* current number of bytes on queue */
    +	unsigned long q_qnum;		/* number of messages in queue */
    +	unsigned long q_qbytes;		/* max number of bytes on queue */
    +	pid_t q_lspid;			/* pid of last msgsnd */
    +	pid_t q_lrpid;			/* last receive pid */
    +
    +	struct list_head q_messages;
    +	struct list_head q_receivers;
    +	struct list_head q_senders;
    +};
    +
     asmlinkage long sys_msgget (key_t key, int msgflg);
     asmlinkage long sys_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);
     asmlinkage long sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg);
    diff -X exclude -ur wirex/lsm/include/linux/security.h lsm/lsm-new/include/linux/security.h
    --- wirex/lsm/include/linux/security.h	Thu Jun 21 08:47:10 2001
    +++ lsm/lsm-new/include/linux/security.h	Thu Jun 21 11:42:36 2001
    @@ -30,6 +30,7 @@
     #include <linux/resource.h>
     #include <linux/ipc.h>
     #include <linux/sem.h>
    +#include <linux/sysctl.h>
     #include <linux/shm.h>
     #include <linux/msg.h>
     
    @@ -138,12 +139,19 @@
     	int (* getinfo)		(int id, int cmd);
     };
     
    +struct msg_msg_security_ops {
    +	int  (* alloc_security)		(struct msg_msg *msg);
    +	void (* free_security)		(struct msg_msg *msg);
    +	int  (* test_message)		(struct msg_msg *msg, long type, int mode);
    +};
    +
     struct msg_queue_security_ops {
    -	int (* create)			(key_t key);	// can i create
    -	int (* permission)		(void);		
    -	int (* setmaxqbytes)		(void);		
    -	int (* setattr)			(void);		// can i set attributes
    -	int (* delete)			(void);		// can i delete
    +	int (* alloc_security)		(struct msg_queue *msq);
    +	void (* free_security)		(struct msg_queue *msq);
    +	int (* associate)		(struct msg_queue *msq, int msqid, int msqflg);
    +	int (* msgctl)			(struct msg_queue *msq, int msqid, int cmd);
    +	int (* msgsnd)			(struct msg_queue *msq, struct msg_msg *msg, int msqid, int msqflg);
    +	int (* msgrcv)			(struct msg_queue *msq, struct msg_msg *msg, int msqid, int msgflg);
     };
     
     struct shm_security_ops {
    @@ -183,6 +191,7 @@
     	int  (* ptrace)			(struct task_struct *parent, struct task_struct *child);		
     	int  (* setcapability)		(void);		
     	int  (* acct)			(struct file *file);
    +	int (* sysctl)			(ctl_table * table, int op);
     	int  (* capable)	        (struct task_struct *tsk, int cap); 
     
     	struct binprm_security_ops	* bprm_ops;
    @@ -193,6 +202,7 @@
     	struct socket_security_ops	* socket_ops;
     	struct module_security_ops 	* module_ops;
     	struct ipc_security_ops		* ipc_ops;
    +	struct msg_msg_security_ops	* msg_msg_ops;
     	struct msg_queue_security_ops	* msg_queue_ops;
     	struct shm_security_ops		* shm_ops;
     	struct sem_security_ops		* sem_ops;
    diff -X exclude -ur wirex/lsm/ipc/msg.c lsm/lsm-new/ipc/msg.c
    --- wirex/lsm/ipc/msg.c	Mon Jun 18 16:40:18 2001
    +++ lsm/lsm-new/ipc/msg.c	Thu Jun 21 11:40:44 2001
    @@ -52,34 +52,6 @@
     	struct msg_msgseg* next;
     	/* the next part of the message follows immediately */
     };
    -/* one msg_msg structure for each message */
    -struct msg_msg {
    -	struct list_head m_list; 
    -	long  m_type;          
    -	int m_ts;           /* message text size */
    -	struct msg_msgseg* next;
    -	/* the actual message follows immediately */
    -};
    -
    -#define DATALEN_MSG	(PAGE_SIZE-sizeof(struct msg_msg))
    -#define DATALEN_SEG	(PAGE_SIZE-sizeof(struct msg_msgseg))
    -
    -/* one msq_queue structure for each present queue on the system */
    -struct msg_queue {
    -	struct kern_ipc_perm q_perm;
    -	time_t q_stime;			/* last msgsnd time */
    -	time_t q_rtime;			/* last msgrcv time */
    -	time_t q_ctime;			/* last change time */
    -	unsigned long q_cbytes;		/* current number of bytes on queue */
    -	unsigned long q_qnum;		/* number of messages in queue */
    -	unsigned long q_qbytes;		/* max number of bytes on queue */
    -	pid_t q_lspid;			/* pid of last msgsnd */
    -	pid_t q_lrpid;			/* last receive pid */
    -
    -	struct list_head q_messages;
    -	struct list_head q_receivers;
    -	struct list_head q_senders;
    -};
     
     #define SEARCH_ANY		1
     #define SEARCH_EQUAL		2
    @@ -117,11 +89,19 @@
     static int newque (key_t key, int msgflg)
     {
     	int id;
    +	int retval;
     	struct msg_queue *msq;
     
     	msq  = (struct msg_queue *) kmalloc (sizeof (*msq), GFP_KERNEL);
     	if (!msq) 
     		return -ENOMEM;
    +
    +	retval = security_ops->msg_queue_ops->alloc_security(msq);
    +	if (retval) {
    +		kfree(msq);
    +		return retval;
    +	}
    +
     	id = ipc_addid(&msg_ids, &msq->q_perm, msg_ctlmni);
     	if(id == -1) {
     		kfree(msq);
    @@ -146,6 +126,9 @@
     static void free_msg(struct msg_msg* msg)
     {
     	struct msg_msgseg* seg;
    +
    +	security_ops->msg_msg_ops->free_security(msg);
    +
     	seg = msg->next;
     	kfree(msg);
     	while(seg != NULL) {
    @@ -200,6 +183,11 @@
     		len -= alen;
     		src = ((char*)src)+alen;
     	}
    +	
    +	err = security_ops->msg_msg_ops->alloc_security(msg);
    +	if (err)
    +		goto out_err;
    +
     	return msg;
     
     out_err:
    @@ -285,6 +273,8 @@
     
     	msq = msg_rmid(id);
     
    +	security_ops->msg_queue_ops->free_security(msq);
    +
     	expunge_all(msq,-EIDRM);
     	ss_wakeup(&msq->q_senders,1);
     	msg_unlock(id);
    @@ -319,7 +309,8 @@
     		msq = msg_lock(id);
     		if(msq==NULL)
     			BUG();
    -		if (ipcperms(&msq->q_perm, msgflg))
    +		if (ipcperms(&msq->q_perm, msgflg) ||
    +		    security_ops->msg_queue_ops->associate(msq, msg_buildid(id, msq->q_perm.seq), msgflg))
     			ret = -EACCES;
     		else
     			ret = msg_buildid(id, msq->q_perm.seq);
    @@ -444,6 +435,11 @@
     		 * due to padding, it's not enough
     		 * to set all member fields.
     		 */
    +
    +		err = security_ops->ipc_ops->getinfo(msqid, cmd);
    +		if (err)
    +			return err;
    +
     		memset(&msginfo,0,sizeof(msginfo));	
     		msginfo.msgmni = msg_ctlmni;
     		msginfo.msgmax = msg_ctlmax;
    @@ -494,6 +490,10 @@
     		if (ipcperms (&msq->q_perm, S_IRUGO))
     			goto out_unlock;
     
    +		err = security_ops->msg_queue_ops->msgctl(msq, msqid, 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;
    @@ -541,6 +541,11 @@
     	{
     		if (setbuf.qbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
     			goto out_unlock_up;
    +
    +		err = security_ops->msg_queue_ops->msgctl(msq, msqid, cmd);
    +		if (err)
    +			goto out_unlock_up;
    +		
     		msq->q_qbytes = setbuf.qbytes;
     
     		ipcp->uid = setbuf.uid;
    @@ -560,6 +565,10 @@
     		break;
     	}
     	case IPC_RMID:
    +		err = security_ops->msg_queue_ops->msgctl(msq, msqid, cmd);
    +		if (err)
    +			goto out_unlock_up;
    +
     		freeque (msqid); 
     		break;
     	}
    @@ -577,6 +586,9 @@
     
     static int testmsg(struct msg_msg* msg,long type,int mode)
     {
    +	if (security_ops->msg_msg_ops->test_message(msg, type, mode))
    +		return 0;
    +
     	switch(mode)
     	{
     		case SEARCH_ANY:
    @@ -657,6 +669,10 @@
     	if (ipcperms(&msq->q_perm, S_IWUGO)) 
     		goto out_unlock_free;
     
    +	err = security_ops->msg_queue_ops->msgsnd(msq, msg, msqid, 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;
    @@ -768,6 +784,11 @@
     			err=-E2BIG;
     			goto out_unlock;
     		}
    +
    +		err = security_ops->msg_queue_ops->msgrcv(msq, msg, msqid, msgflg);
    +		if (err)
    +			goto out_unlock;
    +
     		list_del(&msg->m_list);
     		msq->q_qnum--;
     		msq->q_rtime = CURRENT_TIME;
    diff -X exclude -ur wirex/lsm/kernel/security.c lsm/lsm-new/kernel/security.c
    --- wirex/lsm/kernel/security.c	Thu Jun 21 08:47:10 2001
    +++ lsm/lsm-new/kernel/security.c	Thu Jun 21 11:48:18 2001
    @@ -61,7 +61,8 @@
      	/* capability denied */
      	return -EPERM;
     }
    - 
    +
    +static int dummy_sysctl         (ctl_table * table, int op)     {return 0;}
     static int dummy_binprm_alloc_security(struct linux_binprm *bprm)	{return 0;}
     static void dummy_binprm_free_security	(struct linux_binprm *bprm)		{return;}
     static void dummy_binprm_compute_creds	(struct linux_binprm *bprm)	{return;}
    @@ -123,7 +124,9 @@
     static int dummy_task_setrlimit	(unsigned int resource, struct rlimit *new_rlim)	{return 0;}
     static int dummy_task_setscheduler	(struct task_struct *p, int policy)	{return 0;}
     static int dummy_task_wait		(struct task_struct *p) {return 0;}
    +
     static int dummy_task_kill		(struct task_struct *p, struct siginfo *info, int sig)	{return 0;}
    +
     static int dummy_task_set_label		(char *filename)	{return 0;}
     static void dummy_task_reset_label	(void)			{return;}
     static void dummy_task_kmod_set_label	(void)	                {return;}
    @@ -135,11 +138,16 @@
     static int dummy_ipc_permission	(struct kern_ipc_perm *ipcp, short flag) { return 0; }
     static int dummy_ipc_getinfo	(int id, int cmd) {return 0;}
     
    -static int dummy_msg_queue_create	(key_t key)	{return 0;}
    -static int dummy_msg_queue_permission	(void)	{return 0;}
    -static int dummy_msg_queue_setmaxqbytes	(void)	{return 0;}
    -static int dummy_msg_queue_setattr	(void)	{return 0;}
    -static int dummy_msg_queue_delete	(void)	{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_msg_test_message(struct msg_msg* msg, long type, int mode) {return 0;}
    +
    +static int dummy_msg_queue_alloc_security(struct msg_queue *msq) {return 0;}
    +static void dummy_msg_queue_free_security(struct msg_queue *msq) {return;}
    +static int dummy_msg_queue_associate(struct msg_queue *msq, int msqid, int msqflg) {return 0;}
    +static int dummy_msg_queue_msgctl(struct msg_queue *msq, int msqid, int cmd) {return 0;}
    +static int dummy_msg_queue_msgsnd(struct msg_queue *msq) {return 0;}
    +static int dummy_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, int msqid, int msgflg) {return 0;}
     
     static int dummy_shm_alloc_security (struct shmid_kernel *shp) {return 0;}
     static void dummy_shm_free_security (struct shmid_kernel *shp) {return;}
    @@ -246,12 +254,19 @@
     	getinfo:	dummy_ipc_getinfo,
     };
     
    +static struct msg_msg_security_ops dummy_msg_msg_ops = {
    +	alloc_security:	dummy_msg_msg_alloc_security,
    +	free_security:	dummy_msg_msg_free_security,
    +	test_message:	dummy_msg_msg_test_message,
    +};
    +
     static struct msg_queue_security_ops dummy_msg_queue_ops = {
    -	create:		dummy_msg_queue_create,
    -	permission:	dummy_msg_queue_permission,
    -	setmaxqbytes:	dummy_msg_queue_setmaxqbytes,
    -	setattr:	dummy_msg_queue_setattr,
    -	delete:		dummy_msg_queue_delete,
    +	alloc_security:	dummy_msg_queue_alloc_security,
    +	free_security:	dummy_msg_queue_free_security,
    +	associate:	dummy_msg_queue_associate,
    +	msgctl:		dummy_msg_queue_msgctl,
    +	msgsnd:		dummy_msg_queue_msgsnd,
    +	msgrcv:		dummy_msg_queue_msgrcv,
     };
     
     static struct shm_security_ops dummy_shm_ops = {
    @@ -289,6 +304,7 @@
     	setcapability:		dummy_setcapablity,
     	acct:			dummy_acct,
     	capable:		dummy_capable,
    +	sysctl:			dummy_sysctl,
     
     	bprm_ops:		&dummy_binprm_ops,
     	sb_ops:			&dummy_sb_ops,
    @@ -298,6 +314,7 @@
     	socket_ops:		&dummy_socket_ops,
     	ipc_ops:		&dummy_ipc_ops,
     	module_ops:		&dummy_module_ops,
    +	msg_msg_ops:		&dummy_msg_msg_ops,
     	msg_queue_ops:		&dummy_msg_queue_ops,
     	shm_ops:		&dummy_shm_ops,
     	sem_ops:		&dummy_sem_ops,
    diff -X exclude -ur wirex/lsm/kernel/sysctl.c lsm/lsm-new/kernel/sysctl.c
    --- wirex/lsm/kernel/sysctl.c	Thu Jun 21 08:47:10 2001
    +++ lsm/lsm-new/kernel/sysctl.c	Thu Jun 21 11:39:24 2001
    @@ -391,6 +391,11 @@
     
     static inline int ctl_perm(ctl_table *table, int op)
     {
    +	int error;
    +	error = security_ops->sysctl(table, op);
    +	if(error) {
    +		return error;
    +	}
     	return test_perm(table->mode, op);
     }
     
    
    _______________________________________________
    linux-security-module mailing list
    linux-security-moduleat_private
    http://mail.wirex.com/mailman/listinfo/linux-security-module
    



    This archive was generated by hypermail 2b30 : Thu Jun 21 2001 - 12:27:50 PDT