aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDustin Kirkland <dustin.kirkland@us.ibm.com>2005-11-03 12:15:16 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2006-03-20 14:08:54 -0500
commit8c8570fb8feef2bc166bee75a85748b25cda22d9 (patch)
treeed783d405ea9d5f3d3ccc57fb56c7b7cb2cdfb82
parentc8edc80c8b8c397c53f4f659a05b9ea6208029bf (diff)
[PATCH] Capture selinux subject/object context information.
This patch extends existing audit records with subject/object context information. Audit records associated with filesystem inodes, ipc, and tasks now contain SELinux label information in the field "subj" if the item is performing the action, or in "obj" if the item is the receiver of an action. These labels are collected via hooks in SELinux and appended to the appropriate record in the audit code. This additional information is required for Common Criteria Labeled Security Protection Profile (LSPP). [AV: fixed kmalloc flags use] [folded leak fixes] [folded cleanup from akpm (kfree(NULL)] [folded audit_inode_context() leak fix] [folded akpm's fix for audit_ipc_perm() definition in case of !CONFIG_AUDIT] Signed-off-by: Dustin Kirkland <dustin.kirkland@us.ibm.com> Signed-off-by: David Woodhouse <dwmw2@infradead.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--include/linux/audit.h8
-rw-r--r--include/linux/security.h27
-rw-r--r--ipc/msg.c5
-rw-r--r--ipc/sem.c5
-rw-r--r--ipc/shm.c4
-rw-r--r--kernel/audit.c2
-rw-r--r--kernel/auditsc.c142
-rw-r--r--security/dummy.c6
-rw-r--r--security/selinux/hooks.c96
9 files changed, 226 insertions, 69 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 8fa1a8fbc04..1912d8e8ae9 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -285,13 +285,14 @@ extern void auditsc_get_stamp(struct audit_context *ctx,
285 struct timespec *t, unsigned int *serial); 285 struct timespec *t, unsigned int *serial);
286extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid); 286extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid);
287extern uid_t audit_get_loginuid(struct audit_context *ctx); 287extern uid_t audit_get_loginuid(struct audit_context *ctx);
288extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode); 288extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp);
289extern int audit_socketcall(int nargs, unsigned long *args); 289extern int audit_socketcall(int nargs, unsigned long *args);
290extern int audit_sockaddr(int len, void *addr); 290extern int audit_sockaddr(int len, void *addr);
291extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); 291extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
292extern void audit_signal_info(int sig, struct task_struct *t); 292extern void audit_signal_info(int sig, struct task_struct *t);
293extern int audit_filter_user(struct netlink_skb_parms *cb, int type); 293extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
294extern int audit_filter_type(int type); 294extern int audit_filter_type(int type);
295extern int audit_set_macxattr(const char *name);
295#else 296#else
296#define audit_alloc(t) ({ 0; }) 297#define audit_alloc(t) ({ 0; })
297#define audit_free(t) do { ; } while (0) 298#define audit_free(t) do { ; } while (0)
@@ -306,12 +307,13 @@ extern int audit_filter_type(int type);
306#define audit_receive_filter(t,p,u,s,d,l) ({ -EOPNOTSUPP; }) 307#define audit_receive_filter(t,p,u,s,d,l) ({ -EOPNOTSUPP; })
307#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) 308#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
308#define audit_get_loginuid(c) ({ -1; }) 309#define audit_get_loginuid(c) ({ -1; })
309#define audit_ipc_perms(q,u,g,m) ({ 0; }) 310#define audit_ipc_perms(q,u,g,m,i) ({ 0; })
310#define audit_socketcall(n,a) ({ 0; }) 311#define audit_socketcall(n,a) ({ 0; })
311#define audit_sockaddr(len, addr) ({ 0; }) 312#define audit_sockaddr(len, addr) ({ 0; })
312#define audit_avc_path(dentry, mnt) ({ 0; }) 313#define audit_avc_path(dentry, mnt) ({ 0; })
313#define audit_signal_info(s,t) do { ; } while (0) 314#define audit_signal_info(s,t) do { ; } while (0)
314#define audit_filter_user(cb,t) ({ 1; }) 315#define audit_filter_user(cb,t) ({ 1; })
316#define audit_set_macxattr(n) do { ; } while (0)
315#endif 317#endif
316 318
317#ifdef CONFIG_AUDIT 319#ifdef CONFIG_AUDIT
@@ -340,6 +342,7 @@ extern void audit_send_reply(int pid, int seq, int type,
340 int done, int multi, 342 int done, int multi,
341 void *payload, int size); 343 void *payload, int size);
342extern void audit_log_lost(const char *message); 344extern void audit_log_lost(const char *message);
345extern void audit_panic(const char *message);
343extern struct semaphore audit_netlink_sem; 346extern struct semaphore audit_netlink_sem;
344#else 347#else
345#define audit_log(c,g,t,f,...) do { ; } while (0) 348#define audit_log(c,g,t,f,...) do { ; } while (0)
@@ -350,6 +353,7 @@ extern struct semaphore audit_netlink_sem;
350#define audit_log_hex(a,b,l) do { ; } while (0) 353#define audit_log_hex(a,b,l) do { ; } while (0)
351#define audit_log_untrustedstring(a,s) do { ; } while (0) 354#define audit_log_untrustedstring(a,s) do { ; } while (0)
352#define audit_log_d_path(b,p,d,v) do { ; } while (0) 355#define audit_log_d_path(b,p,d,v) do { ; } while (0)
356#define audit_panic(m) do { ; } while (0)
353#endif 357#endif
354#endif 358#endif
355#endif 359#endif
diff --git a/include/linux/security.h b/include/linux/security.h
index 7cbef482e13..ec0bbbc3ffc 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -869,6 +869,11 @@ struct swap_info_struct;
869 * @ipcp contains the kernel IPC permission structure 869 * @ipcp contains the kernel IPC permission structure
870 * @flag contains the desired (requested) permission set 870 * @flag contains the desired (requested) permission set
871 * Return 0 if permission is granted. 871 * Return 0 if permission is granted.
872 * @ipc_getsecurity:
873 * Copy the security label associated with the ipc object into
874 * @buffer. @buffer may be NULL to request the size of the buffer
875 * required. @size indicates the size of @buffer in bytes. Return
876 * number of bytes used/required on success.
872 * 877 *
873 * Security hooks for individual messages held in System V IPC message queues 878 * Security hooks for individual messages held in System V IPC message queues
874 * @msg_msg_alloc_security: 879 * @msg_msg_alloc_security:
@@ -1168,6 +1173,7 @@ struct security_operations {
1168 int (*inode_getxattr) (struct dentry *dentry, char *name); 1173 int (*inode_getxattr) (struct dentry *dentry, char *name);
1169 int (*inode_listxattr) (struct dentry *dentry); 1174 int (*inode_listxattr) (struct dentry *dentry);
1170 int (*inode_removexattr) (struct dentry *dentry, char *name); 1175 int (*inode_removexattr) (struct dentry *dentry, char *name);
1176 char *(*inode_xattr_getsuffix) (void);
1171 int (*inode_getsecurity)(struct inode *inode, const char *name, void *buffer, size_t size, int err); 1177 int (*inode_getsecurity)(struct inode *inode, const char *name, void *buffer, size_t size, int err);
1172 int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags); 1178 int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
1173 int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size); 1179 int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size);
@@ -1217,6 +1223,7 @@ struct security_operations {
1217 void (*task_to_inode)(struct task_struct *p, struct inode *inode); 1223 void (*task_to_inode)(struct task_struct *p, struct inode *inode);
1218 1224
1219 int (*ipc_permission) (struct kern_ipc_perm * ipcp, short flag); 1225 int (*ipc_permission) (struct kern_ipc_perm * ipcp, short flag);
1226 int (*ipc_getsecurity)(struct kern_ipc_perm *ipcp, void *buffer, size_t size);
1220 1227
1221 int (*msg_msg_alloc_security) (struct msg_msg * msg); 1228 int (*msg_msg_alloc_security) (struct msg_msg * msg);
1222 void (*msg_msg_free_security) (struct msg_msg * msg); 1229 void (*msg_msg_free_security) (struct msg_msg * msg);
@@ -1674,6 +1681,11 @@ static inline int security_inode_removexattr (struct dentry *dentry, char *name)
1674 return security_ops->inode_removexattr (dentry, name); 1681 return security_ops->inode_removexattr (dentry, name);
1675} 1682}
1676 1683
1684static inline const char *security_inode_xattr_getsuffix(void)
1685{
1686 return security_ops->inode_xattr_getsuffix();
1687}
1688
1677static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) 1689static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
1678{ 1690{
1679 if (unlikely (IS_PRIVATE (inode))) 1691 if (unlikely (IS_PRIVATE (inode)))
@@ -1869,6 +1881,11 @@ static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
1869 return security_ops->ipc_permission (ipcp, flag); 1881 return security_ops->ipc_permission (ipcp, flag);
1870} 1882}
1871 1883
1884static inline int security_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
1885{
1886 return security_ops->ipc_getsecurity(ipcp, buffer, size);
1887}
1888
1872static inline int security_msg_msg_alloc (struct msg_msg * msg) 1889static inline int security_msg_msg_alloc (struct msg_msg * msg)
1873{ 1890{
1874 return security_ops->msg_msg_alloc_security (msg); 1891 return security_ops->msg_msg_alloc_security (msg);
@@ -2316,6 +2333,11 @@ static inline int security_inode_removexattr (struct dentry *dentry, char *name)
2316 return cap_inode_removexattr(dentry, name); 2333 return cap_inode_removexattr(dentry, name);
2317} 2334}
2318 2335
2336static inline const char *security_inode_xattr_getsuffix (void)
2337{
2338 return NULL ;
2339}
2340
2319static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) 2341static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
2320{ 2342{
2321 return -EOPNOTSUPP; 2343 return -EOPNOTSUPP;
@@ -2499,6 +2521,11 @@ static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
2499 return 0; 2521 return 0;
2500} 2522}
2501 2523
2524static inline int security_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
2525{
2526 return -EOPNOTSUPP;
2527}
2528
2502static inline int security_msg_msg_alloc (struct msg_msg * msg) 2529static inline int security_msg_msg_alloc (struct msg_msg * msg)
2503{ 2530{
2504 return 0; 2531 return 0;
diff --git a/ipc/msg.c b/ipc/msg.c
index fbf757064a3..8c30ec2f6e3 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -429,8 +429,6 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
429 return -EFAULT; 429 return -EFAULT;
430 if (copy_msqid_from_user (&setbuf, buf, version)) 430 if (copy_msqid_from_user (&setbuf, buf, version))
431 return -EFAULT; 431 return -EFAULT;
432 if ((err = audit_ipc_perms(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode)))
433 return err;
434 break; 432 break;
435 case IPC_RMID: 433 case IPC_RMID:
436 break; 434 break;
@@ -461,6 +459,9 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
461 switch (cmd) { 459 switch (cmd) {
462 case IPC_SET: 460 case IPC_SET:
463 { 461 {
462 if ((err = audit_ipc_perms(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode, ipcp)))
463 goto out_unlock_up;
464
464 err = -EPERM; 465 err = -EPERM;
465 if (setbuf.qbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE)) 466 if (setbuf.qbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
466 goto out_unlock_up; 467 goto out_unlock_up;
diff --git a/ipc/sem.c b/ipc/sem.c
index 31fd4027d2b..59696a840be 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -809,8 +809,6 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
809 if(cmd == IPC_SET) { 809 if(cmd == IPC_SET) {
810 if(copy_semid_from_user (&setbuf, arg.buf, version)) 810 if(copy_semid_from_user (&setbuf, arg.buf, version))
811 return -EFAULT; 811 return -EFAULT;
812 if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode)))
813 return err;
814 } 812 }
815 sma = sem_lock(semid); 813 sma = sem_lock(semid);
816 if(sma==NULL) 814 if(sma==NULL)
@@ -821,7 +819,6 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
821 goto out_unlock; 819 goto out_unlock;
822 } 820 }
823 ipcp = &sma->sem_perm; 821 ipcp = &sma->sem_perm;
824
825 if (current->euid != ipcp->cuid && 822 if (current->euid != ipcp->cuid &&
826 current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) { 823 current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
827 err=-EPERM; 824 err=-EPERM;
@@ -838,6 +835,8 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
838 err = 0; 835 err = 0;
839 break; 836 break;
840 case IPC_SET: 837 case IPC_SET:
838 if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode, ipcp)))
839 goto out_unlock;
841 ipcp->uid = setbuf.uid; 840 ipcp->uid = setbuf.uid;
842 ipcp->gid = setbuf.gid; 841 ipcp->gid = setbuf.gid;
843 ipcp->mode = (ipcp->mode & ~S_IRWXUGO) 842 ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
diff --git a/ipc/shm.c b/ipc/shm.c
index 9162123a7b2..a88c8a02e7f 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -620,13 +620,13 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
620 err = -EFAULT; 620 err = -EFAULT;
621 goto out; 621 goto out;
622 } 622 }
623 if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode)))
624 return err;
625 down(&shm_ids.sem); 623 down(&shm_ids.sem);
626 shp = shm_lock(shmid); 624 shp = shm_lock(shmid);
627 err=-EINVAL; 625 err=-EINVAL;
628 if(shp==NULL) 626 if(shp==NULL)
629 goto out_up; 627 goto out_up;
628 if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode, &(shp->shm_perm))))
629 goto out_unlock_up;
630 err = shm_checkid(shp,shmid); 630 err = shm_checkid(shp,shmid);
631 if(err) 631 if(err)
632 goto out_unlock_up; 632 goto out_unlock_up;
diff --git a/kernel/audit.c b/kernel/audit.c
index 1c3eb1b12bf..45c123ef77a 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -142,7 +142,7 @@ static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
142 nlh->nlmsg_pid = pid; 142 nlh->nlmsg_pid = pid;
143} 143}
144 144
145static void audit_panic(const char *message) 145void audit_panic(const char *message)
146{ 146{
147 switch (audit_failure) 147 switch (audit_failure)
148 { 148 {
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 31917ac730a..4e2256ec7cf 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -34,6 +34,9 @@
34 * 34 *
35 * Modified by Amy Griffis <amy.griffis@hp.com> to collect additional 35 * Modified by Amy Griffis <amy.griffis@hp.com> to collect additional
36 * filesystem information. 36 * filesystem information.
37 *
38 * Subject and object context labeling support added by <danjones@us.ibm.com>
39 * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance.
37 */ 40 */
38 41
39#include <linux/init.h> 42#include <linux/init.h>
@@ -53,6 +56,7 @@
53#include <linux/netlink.h> 56#include <linux/netlink.h>
54#include <linux/compiler.h> 57#include <linux/compiler.h>
55#include <asm/unistd.h> 58#include <asm/unistd.h>
59#include <linux/security.h>
56 60
57/* 0 = no checking 61/* 0 = no checking
58 1 = put_count checking 62 1 = put_count checking
@@ -109,6 +113,7 @@ struct audit_names {
109 uid_t uid; 113 uid_t uid;
110 gid_t gid; 114 gid_t gid;
111 dev_t rdev; 115 dev_t rdev;
116 char *ctx;
112}; 117};
113 118
114struct audit_aux_data { 119struct audit_aux_data {
@@ -125,6 +130,7 @@ struct audit_aux_data_ipcctl {
125 uid_t uid; 130 uid_t uid;
126 gid_t gid; 131 gid_t gid;
127 mode_t mode; 132 mode_t mode;
133 char *ctx;
128}; 134};
129 135
130struct audit_aux_data_socketcall { 136struct audit_aux_data_socketcall {
@@ -743,10 +749,11 @@ static inline void audit_free_names(struct audit_context *context)
743 context->serial, context->major, context->in_syscall, 749 context->serial, context->major, context->in_syscall,
744 context->name_count, context->put_count, 750 context->name_count, context->put_count,
745 context->ino_count); 751 context->ino_count);
746 for (i = 0; i < context->name_count; i++) 752 for (i = 0; i < context->name_count; i++) {
747 printk(KERN_ERR "names[%d] = %p = %s\n", i, 753 printk(KERN_ERR "names[%d] = %p = %s\n", i,
748 context->names[i].name, 754 context->names[i].name,
749 context->names[i].name ?: "(null)"); 755 context->names[i].name ?: "(null)");
756 }
750 dump_stack(); 757 dump_stack();
751 return; 758 return;
752 } 759 }
@@ -756,9 +763,13 @@ static inline void audit_free_names(struct audit_context *context)
756 context->ino_count = 0; 763 context->ino_count = 0;
757#endif 764#endif
758 765
759 for (i = 0; i < context->name_count; i++) 766 for (i = 0; i < context->name_count; i++) {
767 char *p = context->names[i].ctx;
768 context->names[i].ctx = NULL;
769 kfree(p);
760 if (context->names[i].name) 770 if (context->names[i].name)
761 __putname(context->names[i].name); 771 __putname(context->names[i].name);
772 }
762 context->name_count = 0; 773 context->name_count = 0;
763 if (context->pwd) 774 if (context->pwd)
764 dput(context->pwd); 775 dput(context->pwd);
@@ -778,6 +789,12 @@ static inline void audit_free_aux(struct audit_context *context)
778 dput(axi->dentry); 789 dput(axi->dentry);
779 mntput(axi->mnt); 790 mntput(axi->mnt);
780 } 791 }
792 if ( aux->type == AUDIT_IPC ) {
793 struct audit_aux_data_ipcctl *axi = (void *)aux;
794 if (axi->ctx)
795 kfree(axi->ctx);
796 }
797
781 context->aux = aux->next; 798 context->aux = aux->next;
782 kfree(aux); 799 kfree(aux);
783 } 800 }
@@ -862,7 +879,38 @@ static inline void audit_free_context(struct audit_context *context)
862 printk(KERN_ERR "audit: freed %d contexts\n", count); 879 printk(KERN_ERR "audit: freed %d contexts\n", count);
863} 880}
864 881
865static void audit_log_task_info(struct audit_buffer *ab) 882static void audit_log_task_context(struct audit_buffer *ab, gfp_t gfp_mask)
883{
884 char *ctx = NULL;
885 ssize_t len = 0;
886
887 len = security_getprocattr(current, "current", NULL, 0);
888 if (len < 0) {
889 if (len != -EINVAL)
890 goto error_path;
891 return;
892 }
893
894 ctx = kmalloc(len, gfp_mask);
895 if (!ctx) {
896 goto error_path;
897 return;
898 }
899
900 len = security_getprocattr(current, "current", ctx, len);
901 if (len < 0 )
902 goto error_path;
903
904 audit_log_format(ab, " subj=%s", ctx);
905
906error_path:
907 if (ctx)
908 kfree(ctx);
909 audit_panic("security_getprocattr error in audit_log_task_context");
910 return;
911}
912
913static void audit_log_task_info(struct audit_buffer *ab, gfp_t gfp_mask)
866{ 914{
867 char name[sizeof(current->comm)]; 915 char name[sizeof(current->comm)];
868 struct mm_struct *mm = current->mm; 916 struct mm_struct *mm = current->mm;
@@ -875,6 +923,10 @@ static void audit_log_task_info(struct audit_buffer *ab)
875 if (!mm) 923 if (!mm)
876 return; 924 return;
877 925
926 /*
927 * this is brittle; all callers that pass GFP_ATOMIC will have
928 * NULL current->mm and we won't get here.
929 */
878 down_read(&mm->mmap_sem); 930 down_read(&mm->mmap_sem);
879 vma = mm->mmap; 931 vma = mm->mmap;
880 while (vma) { 932 while (vma) {
@@ -888,6 +940,7 @@ static void audit_log_task_info(struct audit_buffer *ab)
888 vma = vma->vm_next; 940 vma = vma->vm_next;
889 } 941 }
890 up_read(&mm->mmap_sem); 942 up_read(&mm->mmap_sem);
943 audit_log_task_context(ab, gfp_mask);
891} 944}
892 945
893static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask) 946static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
@@ -923,7 +976,7 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
923 context->gid, 976 context->gid,
924 context->euid, context->suid, context->fsuid, 977 context->euid, context->suid, context->fsuid,
925 context->egid, context->sgid, context->fsgid); 978 context->egid, context->sgid, context->fsgid);
926 audit_log_task_info(ab); 979 audit_log_task_info(ab, gfp_mask);
927 audit_log_end(ab); 980 audit_log_end(ab);
928 981
929 for (aux = context->aux; aux; aux = aux->next) { 982 for (aux = context->aux; aux; aux = aux->next) {
@@ -936,8 +989,8 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
936 case AUDIT_IPC: { 989 case AUDIT_IPC: {
937 struct audit_aux_data_ipcctl *axi = (void *)aux; 990 struct audit_aux_data_ipcctl *axi = (void *)aux;
938 audit_log_format(ab, 991 audit_log_format(ab,
939 " qbytes=%lx iuid=%u igid=%u mode=%x", 992 " qbytes=%lx iuid=%u igid=%u mode=%x obj=%s",
940 axi->qbytes, axi->uid, axi->gid, axi->mode); 993 axi->qbytes, axi->uid, axi->gid, axi->mode, axi->ctx);
941 break; } 994 break; }
942 995
943 case AUDIT_SOCKETCALL: { 996 case AUDIT_SOCKETCALL: {
@@ -1001,6 +1054,11 @@ static void audit_log_exit(struct audit_context *context, gfp_t gfp_mask)
1001 context->names[i].gid, 1054 context->names[i].gid,
1002 MAJOR(context->names[i].rdev), 1055 MAJOR(context->names[i].rdev),
1003 MINOR(context->names[i].rdev)); 1056 MINOR(context->names[i].rdev));
1057 if (context->names[i].ctx) {
1058 audit_log_format(ab, " obj=%s",
1059 context->names[i].ctx);
1060 }
1061
1004 audit_log_end(ab); 1062 audit_log_end(ab);
1005 } 1063 }
1006} 1064}
@@ -1243,6 +1301,39 @@ void audit_putname(const char *name)
1243#endif 1301#endif
1244} 1302}
1245 1303
1304void audit_inode_context(int idx, const struct inode *inode)
1305{
1306 struct audit_context *context = current->audit_context;
1307 char *ctx = NULL;
1308 int len = 0;
1309
1310 if (!security_inode_xattr_getsuffix())
1311 return;
1312
1313 len = security_inode_getsecurity(inode, (char *)security_inode_xattr_getsuffix(), NULL, 0, 0);
1314 if (len < 0)
1315 goto error_path;
1316
1317 ctx = kmalloc(len, GFP_KERNEL);
1318 if (!ctx)
1319 goto error_path;
1320
1321 len = security_inode_getsecurity(inode, (char *)security_inode_xattr_getsuffix(), ctx, len, 0);
1322 if (len < 0)
1323 goto error_path;
1324
1325 kfree(context->names[idx].ctx);
1326 context->names[idx].ctx = ctx;
1327 return;
1328
1329error_path:
1330 if (ctx)
1331 kfree(ctx);
1332 audit_panic("error in audit_inode_context");
1333 return;
1334}
1335
1336
1246/** 1337/**
1247 * audit_inode - store the inode and device from a lookup 1338 * audit_inode - store the inode and device from a lookup
1248 * @name: name being audited 1339 * @name: name being audited
@@ -1282,6 +1373,7 @@ void __audit_inode(const char *name, const struct inode *inode, unsigned flags)
1282 context->names[idx].uid = inode->i_uid; 1373 context->names[idx].uid = inode->i_uid;
1283 context->names[idx].gid = inode->i_gid; 1374 context->names[idx].gid = inode->i_gid;
1284 context->names[idx].rdev = inode->i_rdev; 1375 context->names[idx].rdev = inode->i_rdev;
1376 audit_inode_context(idx, inode);
1285 if ((flags & LOOKUP_PARENT) && (strcmp(name, "/") != 0) && 1377 if ((flags & LOOKUP_PARENT) && (strcmp(name, "/") != 0) &&
1286 (strcmp(name, ".") != 0)) { 1378 (strcmp(name, ".") != 0)) {
1287 context->names[idx].ino = (unsigned long)-1; 1379 context->names[idx].ino = (unsigned long)-1;
@@ -1363,6 +1455,7 @@ update_context:
1363 context->names[idx].uid = inode->i_uid; 1455 context->names[idx].uid = inode->i_uid;
1364 context->names[idx].gid = inode->i_gid; 1456 context->names[idx].gid = inode->i_gid;
1365 context->names[idx].rdev = inode->i_rdev; 1457 context->names[idx].rdev = inode->i_rdev;
1458 audit_inode_context(idx, inode);
1366 } 1459 }
1367} 1460}
1368 1461
@@ -1423,6 +1516,38 @@ uid_t audit_get_loginuid(struct audit_context *ctx)
1423 return ctx ? ctx->loginuid : -1; 1516 return ctx ? ctx->loginuid : -1;
1424} 1517}
1425 1518
1519static char *audit_ipc_context(struct kern_ipc_perm *ipcp)
1520{
1521 struct audit_context *context = current->audit_context;
1522 char *ctx = NULL;
1523 int len = 0;
1524
1525 if (likely(!context))
1526 return NULL;
1527
1528 len = security_ipc_getsecurity(ipcp, NULL, 0);
1529 if (len == -EOPNOTSUPP)
1530 goto ret;
1531 if (len < 0)
1532 goto error_path;
1533
1534 ctx = kmalloc(len, GFP_ATOMIC);
1535 if (!ctx)
1536 goto error_path;
1537
1538 len = security_ipc_getsecurity(ipcp, ctx, len);
1539 if (len < 0)
1540 goto error_path;
1541
1542 return ctx;
1543
1544error_path:
1545 kfree(ctx);
1546 audit_panic("error in audit_ipc_context");
1547ret:
1548 return NULL;
1549}
1550
1426/** 1551/**
1427 * audit_ipc_perms - record audit data for ipc 1552 * audit_ipc_perms - record audit data for ipc
1428 * @qbytes: msgq bytes 1553 * @qbytes: msgq bytes
@@ -1432,7 +1557,7 @@ uid_t audit_get_loginuid(struct audit_context *ctx)
1432 * 1557 *
1433 * Returns 0 for success or NULL context or < 0 on error. 1558 * Returns 0 for success or NULL context or < 0 on error.
1434 */ 1559 */
1435int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) 1560int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp)
1436{ 1561{
1437 struct audit_aux_data_ipcctl *ax; 1562 struct audit_aux_data_ipcctl *ax;
1438 struct audit_context *context = current->audit_context; 1563 struct audit_context *context = current->audit_context;
@@ -1440,7 +1565,7 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
1440 if (likely(!context)) 1565 if (likely(!context))
1441 return 0; 1566 return 0;
1442 1567
1443 ax = kmalloc(sizeof(*ax), GFP_KERNEL); 1568 ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
1444 if (!ax) 1569 if (!ax)
1445 return -ENOMEM; 1570 return -ENOMEM;
1446 1571
@@ -1448,6 +1573,7 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
1448 ax->uid = uid; 1573 ax->uid = uid;
1449 ax->gid = gid; 1574 ax->gid = gid;
1450 ax->mode = mode; 1575 ax->mode = mode;
1576 ax->ctx = audit_ipc_context(ipcp);
1451 1577
1452 ax->d.type = AUDIT_IPC; 1578 ax->d.type = AUDIT_IPC;
1453 ax->d.next = context->aux; 1579 ax->d.next = context->aux;
diff --git a/security/dummy.c b/security/dummy.c
index f1a5bd98bf1..6febe7d39fa 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -558,6 +558,11 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
558 return 0; 558 return 0;
559} 559}
560 560
561static int dummy_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
562{
563 return -EOPNOTSUPP;
564}
565
561static int dummy_msg_msg_alloc_security (struct msg_msg *msg) 566static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
562{ 567{
563 return 0; 568 return 0;
@@ -959,6 +964,7 @@ void security_fixup_ops (struct security_operations *ops)
959 set_to_dummy_if_null(ops, task_reparent_to_init); 964 set_to_dummy_if_null(ops, task_reparent_to_init);
960 set_to_dummy_if_null(ops, task_to_inode); 965 set_to_dummy_if_null(ops, task_to_inode);
961 set_to_dummy_if_null(ops, ipc_permission); 966 set_to_dummy_if_null(ops, ipc_permission);
967 set_to_dummy_if_null(ops, ipc_getsecurity);
962 set_to_dummy_if_null(ops, msg_msg_alloc_security); 968 set_to_dummy_if_null(ops, msg_msg_alloc_security);
963 set_to_dummy_if_null(ops, msg_msg_free_security); 969 set_to_dummy_if_null(ops, msg_msg_free_security);
964 set_to_dummy_if_null(ops, msg_queue_alloc_security); 970 set_to_dummy_if_null(ops, msg_queue_alloc_security);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b65c201e9ff..9c08a19cc81 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -117,6 +117,32 @@ static struct security_operations *secondary_ops = NULL;
117static LIST_HEAD(superblock_security_head); 117static LIST_HEAD(superblock_security_head);
118static DEFINE_SPINLOCK(sb_security_lock); 118static DEFINE_SPINLOCK(sb_security_lock);
119 119
120/* Return security context for a given sid or just the context
121 length if the buffer is null or length is 0 */
122static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
123{
124 char *context;
125 unsigned len;
126 int rc;
127
128 rc = security_sid_to_context(sid, &context, &len);
129 if (rc)
130 return rc;
131
132 if (!buffer || !size)
133 goto getsecurity_exit;
134
135 if (size < len) {
136 len = -ERANGE;
137 goto getsecurity_exit;
138 }
139 memcpy(buffer, context, len);
140
141getsecurity_exit:
142 kfree(context);
143 return len;
144}
145
120/* Allocate and free functions for each kind of security blob. */ 146/* Allocate and free functions for each kind of security blob. */
121 147
122static int task_alloc_security(struct task_struct *task) 148static int task_alloc_security(struct task_struct *task)
@@ -2209,6 +2235,11 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name)
2209 return -EACCES; 2235 return -EACCES;
2210} 2236}
2211 2237
2238static const char *selinux_inode_xattr_getsuffix(void)
2239{
2240 return XATTR_SELINUX_SUFFIX;
2241}
2242
2212/* 2243/*
2213 * Copy the in-core inode security context value to the user. If the 2244 * Copy the in-core inode security context value to the user. If the
2214 * getxattr() prior to this succeeded, check to see if we need to 2245 * getxattr() prior to this succeeded, check to see if we need to
@@ -2219,44 +2250,11 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name)
2219static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err) 2250static int selinux_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size, int err)
2220{ 2251{
2221 struct inode_security_struct *isec = inode->i_security; 2252 struct inode_security_struct *isec = inode->i_security;
2222 char *context;
2223 unsigned len;
2224 int rc;
2225
2226 if (strcmp(name, XATTR_SELINUX_SUFFIX)) {
2227 rc = -EOPNOTSUPP;
2228 goto out;
2229 }
2230
2231 rc = security_sid_to_context(isec->sid, &context, &len);
2232 if (rc)
2233 goto out;
2234
2235 /* Probe for required buffer size */
2236 if (!buffer || !size) {
2237 rc = len;
2238 goto out_free;
2239 }
2240 2253
2241 if (size < len) { 2254 if (strcmp(name, XATTR_SELINUX_SUFFIX))
2242 rc = -ERANGE; 2255 return -EOPNOTSUPP;
2243 goto out_free;
2244 }
2245 2256
2246 if (err > 0) { 2257 return selinux_getsecurity(isec->sid, buffer, size);
2247 if ((len == err) && !(memcmp(context, buffer, len))) {
2248 /* Don't need to canonicalize value */
2249 rc = err;
2250 goto out_free;
2251 }
2252 memset(buffer, 0, size);
2253 }
2254 memcpy(buffer, context, len);
2255 rc = len;
2256out_free:
2257 kfree(context);
2258out:
2259 return rc;
2260} 2258}
2261 2259
2262static int selinux_inode_setsecurity(struct inode *inode, const char *name, 2260static int selinux_inode_setsecurity(struct inode *inode, const char *name,
@@ -4022,6 +4020,13 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
4022 return ipc_has_perm(ipcp, av); 4020 return ipc_has_perm(ipcp, av);
4023} 4021}
4024 4022
4023static int selinux_ipc_getsecurity(struct kern_ipc_perm *ipcp, void *buffer, size_t size)
4024{
4025 struct ipc_security_struct *isec = ipcp->security;
4026
4027 return selinux_getsecurity(isec->sid, buffer, size);
4028}
4029
4025/* module stacking operations */ 4030/* module stacking operations */
4026static int selinux_register_security (const char *name, struct security_operations *ops) 4031static int selinux_register_security (const char *name, struct security_operations *ops)
4027{ 4032{
@@ -4063,8 +4068,7 @@ static int selinux_getprocattr(struct task_struct *p,
4063 char *name, void *value, size_t size) 4068 char *name, void *value, size_t size)
4064{ 4069{
4065 struct task_security_struct *tsec; 4070 struct task_security_struct *tsec;
4066 u32 sid, len; 4071 u32 sid;
4067 char *context;
4068 int error; 4072 int error;
4069 4073
4070 if (current != p) { 4074 if (current != p) {
@@ -4073,9 +4077,6 @@ static int selinux_getprocattr(struct task_struct *p,
4073 return error; 4077 return error;
4074 } 4078 }
4075 4079
4076 if (!size)
4077 return -ERANGE;
4078
4079 tsec = p->security; 4080 tsec = p->security;
4080 4081
4081 if (!strcmp(name, "current")) 4082 if (!strcmp(name, "current"))
@@ -4092,16 +4093,7 @@ static int selinux_getprocattr(struct task_struct *p,
4092 if (!sid) 4093 if (!sid)
4093 return 0; 4094 return 0;
4094 4095
4095 error = security_sid_to_context(sid, &context, &len); 4096 return selinux_getsecurity(sid, value, size);
4096 if (error)
4097 return error;
4098 if (len > size) {
4099 kfree(context);
4100 return -ERANGE;
4101 }
4102 memcpy(value, context, len);
4103 kfree(context);
4104 return len;
4105} 4097}
4106 4098
4107static int selinux_setprocattr(struct task_struct *p, 4099static int selinux_setprocattr(struct task_struct *p,
@@ -4259,6 +4251,7 @@ static struct security_operations selinux_ops = {
4259 .inode_getxattr = selinux_inode_getxattr, 4251 .inode_getxattr = selinux_inode_getxattr,
4260 .inode_listxattr = selinux_inode_listxattr, 4252 .inode_listxattr = selinux_inode_listxattr,
4261 .inode_removexattr = selinux_inode_removexattr, 4253 .inode_removexattr = selinux_inode_removexattr,
4254 .inode_xattr_getsuffix = selinux_inode_xattr_getsuffix,
4262 .inode_getsecurity = selinux_inode_getsecurity, 4255 .inode_getsecurity = selinux_inode_getsecurity,
4263 .inode_setsecurity = selinux_inode_setsecurity, 4256 .inode_setsecurity = selinux_inode_setsecurity,
4264 .inode_listsecurity = selinux_inode_listsecurity, 4257 .inode_listsecurity = selinux_inode_listsecurity,
@@ -4296,6 +4289,7 @@ static struct security_operations selinux_ops = {
4296 .task_to_inode = selinux_task_to_inode, 4289 .task_to_inode = selinux_task_to_inode,
4297 4290
4298 .ipc_permission = selinux_ipc_permission, 4291 .ipc_permission = selinux_ipc_permission,
4292 .ipc_getsecurity = selinux_ipc_getsecurity,
4299 4293
4300 .msg_msg_alloc_security = selinux_msg_msg_alloc_security, 4294 .msg_msg_alloc_security = selinux_msg_msg_alloc_security,
4301 .msg_msg_free_security = selinux_msg_msg_free_security, 4295 .msg_msg_free_security = selinux_msg_msg_free_security,