diff options
author | Stephen Smalley <sds@tycho.nsa.gov> | 2005-05-20 19:15:52 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@shinybook.infradead.org> | 2005-05-20 19:15:52 -0400 |
commit | 011161051bbc25f7f8b7df059dbd934c534443f0 (patch) | |
tree | f1ca3727e4130cacad86dfdae65e7533fcb67784 | |
parent | fb19b4c6aa024837a0071f07baa07dbf49d07151 (diff) |
AUDIT: Avoid sleeping function in SElinux AVC audit.
This patch changes the SELinux AVC to defer logging of paths to the audit
framework upon syscall exit, by saving a reference to the (dentry,vfsmount)
pair in an auxiliary audit item on the current audit context for processing
by audit_log_exit.
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-rw-r--r-- | include/linux/audit.h | 3 | ||||
-rw-r--r-- | kernel/auditsc.c | 40 | ||||
-rw-r--r-- | security/selinux/avc.c | 17 |
3 files changed, 51 insertions, 9 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h index 17ea5d522d81..4b7caf0c6e10 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -69,6 +69,7 @@ | |||
69 | 69 | ||
70 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ | 70 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ |
71 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ | 71 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ |
72 | #define AUDIT_AVC_PATH 1402 /* dentry, vfsmount pair from avc */ | ||
72 | 73 | ||
73 | #define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */ | 74 | #define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */ |
74 | 75 | ||
@@ -225,6 +226,7 @@ extern uid_t audit_get_loginuid(struct audit_context *ctx); | |||
225 | extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode); | 226 | extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode); |
226 | extern int audit_socketcall(int nargs, unsigned long *args); | 227 | extern int audit_socketcall(int nargs, unsigned long *args); |
227 | extern int audit_sockaddr(int len, void *addr); | 228 | extern int audit_sockaddr(int len, void *addr); |
229 | extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); | ||
228 | extern void audit_signal_info(int sig, struct task_struct *t); | 230 | extern void audit_signal_info(int sig, struct task_struct *t); |
229 | #else | 231 | #else |
230 | #define audit_alloc(t) ({ 0; }) | 232 | #define audit_alloc(t) ({ 0; }) |
@@ -240,6 +242,7 @@ extern void audit_signal_info(int sig, struct task_struct *t); | |||
240 | #define audit_ipc_perms(q,u,g,m) ({ 0; }) | 242 | #define audit_ipc_perms(q,u,g,m) ({ 0; }) |
241 | #define audit_socketcall(n,a) ({ 0; }) | 243 | #define audit_socketcall(n,a) ({ 0; }) |
242 | #define audit_sockaddr(len, addr) ({ 0; }) | 244 | #define audit_sockaddr(len, addr) ({ 0; }) |
245 | #define audit_avc_path(dentry, mnt) ({ 0; }) | ||
243 | #define audit_signal_info(s,t) do { ; } while (0) | 246 | #define audit_signal_info(s,t) do { ; } while (0) |
244 | #endif | 247 | #endif |
245 | 248 | ||
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 78d7a13fc86f..8dc5b2767145 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/types.h> | 34 | #include <asm/types.h> |
35 | #include <linux/mm.h> | 35 | #include <linux/mm.h> |
36 | #include <linux/module.h> | 36 | #include <linux/module.h> |
37 | #include <linux/mount.h> | ||
37 | #include <linux/socket.h> | 38 | #include <linux/socket.h> |
38 | #include <linux/audit.h> | 39 | #include <linux/audit.h> |
39 | #include <linux/personality.h> | 40 | #include <linux/personality.h> |
@@ -124,6 +125,11 @@ struct audit_aux_data_sockaddr { | |||
124 | char a[0]; | 125 | char a[0]; |
125 | }; | 126 | }; |
126 | 127 | ||
128 | struct audit_aux_data_path { | ||
129 | struct audit_aux_data d; | ||
130 | struct dentry *dentry; | ||
131 | struct vfsmount *mnt; | ||
132 | }; | ||
127 | 133 | ||
128 | /* The per-task audit context. */ | 134 | /* The per-task audit context. */ |
129 | struct audit_context { | 135 | struct audit_context { |
@@ -553,6 +559,11 @@ static inline void audit_free_aux(struct audit_context *context) | |||
553 | struct audit_aux_data *aux; | 559 | struct audit_aux_data *aux; |
554 | 560 | ||
555 | while ((aux = context->aux)) { | 561 | while ((aux = context->aux)) { |
562 | if (aux->type == AUDIT_AVC_PATH) { | ||
563 | struct audit_aux_data_path *axi = (void *)aux; | ||
564 | dput(axi->dentry); | ||
565 | mntput(axi->mnt); | ||
566 | } | ||
556 | context->aux = aux->next; | 567 | context->aux = aux->next; |
557 | kfree(aux); | 568 | kfree(aux); |
558 | } | 569 | } |
@@ -724,6 +735,14 @@ static void audit_log_exit(struct audit_context *context) | |||
724 | audit_log_format(ab, "saddr="); | 735 | audit_log_format(ab, "saddr="); |
725 | audit_log_hex(ab, axs->a, axs->len); | 736 | audit_log_hex(ab, axs->a, axs->len); |
726 | break; } | 737 | break; } |
738 | |||
739 | case AUDIT_AVC_PATH: { | ||
740 | struct audit_aux_data_path *axi = (void *)aux; | ||
741 | audit_log_d_path(ab, "path=", axi->dentry, axi->mnt); | ||
742 | dput(axi->dentry); | ||
743 | mntput(axi->mnt); | ||
744 | break; } | ||
745 | |||
727 | } | 746 | } |
728 | audit_log_end(ab); | 747 | audit_log_end(ab); |
729 | 748 | ||
@@ -1124,6 +1143,27 @@ int audit_sockaddr(int len, void *a) | |||
1124 | return 0; | 1143 | return 0; |
1125 | } | 1144 | } |
1126 | 1145 | ||
1146 | int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt) | ||
1147 | { | ||
1148 | struct audit_aux_data_path *ax; | ||
1149 | struct audit_context *context = current->audit_context; | ||
1150 | |||
1151 | if (likely(!context)) | ||
1152 | return 0; | ||
1153 | |||
1154 | ax = kmalloc(sizeof(*ax), GFP_ATOMIC); | ||
1155 | if (!ax) | ||
1156 | return -ENOMEM; | ||
1157 | |||
1158 | ax->dentry = dget(dentry); | ||
1159 | ax->mnt = mntget(mnt); | ||
1160 | |||
1161 | ax->d.type = AUDIT_AVC_PATH; | ||
1162 | ax->d.next = context->aux; | ||
1163 | context->aux = (void *)ax; | ||
1164 | return 0; | ||
1165 | } | ||
1166 | |||
1127 | void audit_signal_info(int sig, struct task_struct *t) | 1167 | void audit_signal_info(int sig, struct task_struct *t) |
1128 | { | 1168 | { |
1129 | extern pid_t audit_sig_pid; | 1169 | extern pid_t audit_sig_pid; |
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 62b963aca275..0fbc3e98c5ea 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -573,13 +573,10 @@ void avc_audit(u32 ssid, u32 tsid, | |||
573 | case AVC_AUDIT_DATA_FS: | 573 | case AVC_AUDIT_DATA_FS: |
574 | if (a->u.fs.dentry) { | 574 | if (a->u.fs.dentry) { |
575 | struct dentry *dentry = a->u.fs.dentry; | 575 | struct dentry *dentry = a->u.fs.dentry; |
576 | if (a->u.fs.mnt) { | 576 | if (a->u.fs.mnt) |
577 | audit_log_d_path(ab, "path=", dentry, | 577 | audit_avc_path(dentry, a->u.fs.mnt); |
578 | a->u.fs.mnt); | 578 | audit_log_format(ab, " name=%s", |
579 | } else { | 579 | dentry->d_name.name); |
580 | audit_log_format(ab, " name=%s", | ||
581 | dentry->d_name.name); | ||
582 | } | ||
583 | inode = dentry->d_inode; | 580 | inode = dentry->d_inode; |
584 | } else if (a->u.fs.inode) { | 581 | } else if (a->u.fs.inode) { |
585 | struct dentry *dentry; | 582 | struct dentry *dentry; |
@@ -630,8 +627,10 @@ void avc_audit(u32 ssid, u32 tsid, | |||
630 | case AF_UNIX: | 627 | case AF_UNIX: |
631 | u = unix_sk(sk); | 628 | u = unix_sk(sk); |
632 | if (u->dentry) { | 629 | if (u->dentry) { |
633 | audit_log_d_path(ab, "path=", | 630 | audit_avc_path(u->dentry, u->mnt); |
634 | u->dentry, u->mnt); | 631 | audit_log_format(ab, " name=%s", |
632 | u->dentry->d_name.name); | ||
633 | |||
635 | break; | 634 | break; |
636 | } | 635 | } |
637 | if (!u->addr) | 636 | if (!u->addr) |