diff options
-rw-r--r-- | fs/exec.c | 6 | ||||
-rw-r--r-- | include/linux/audit.h | 6 | ||||
-rw-r--r-- | kernel/audit.c | 8 | ||||
-rw-r--r-- | kernel/auditsc.c | 51 |
4 files changed, 67 insertions, 4 deletions
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/rmap.h> | 49 | #include <linux/rmap.h> |
50 | #include <linux/acct.h> | 50 | #include <linux/acct.h> |
51 | #include <linux/cn_proc.h> | 51 | #include <linux/cn_proc.h> |
52 | #include <linux/audit.h> | ||
52 | 53 | ||
53 | #include <asm/uaccess.h> | 54 | #include <asm/uaccess.h> |
54 | #include <asm/mmu_context.h> | 55 | #include <asm/mmu_context.h> |
@@ -1085,6 +1086,11 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) | |||
1085 | /* kernel module loader fixup */ | 1086 | /* kernel module loader fixup */ |
1086 | /* so we don't try to load run modprobe in kernel space. */ | 1087 | /* so we don't try to load run modprobe in kernel space. */ |
1087 | set_fs(USER_DS); | 1088 | set_fs(USER_DS); |
1089 | |||
1090 | retval = audit_bprm(bprm); | ||
1091 | if (retval) | ||
1092 | return retval; | ||
1093 | |||
1088 | retval = -ENOENT; | 1094 | retval = -ENOENT; |
1089 | for (try=0; try<2; try++) { | 1095 | for (try=0; try<2; try++) { |
1090 | read_lock(&binfmt_lock); | 1096 | read_lock(&binfmt_lock); |
diff --git a/include/linux/audit.h b/include/linux/audit.h index e65399bf2710..1a221b65f7b7 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -83,6 +83,7 @@ | |||
83 | #define AUDIT_CONFIG_CHANGE 1305 /* Audit system configuration change */ | 83 | #define AUDIT_CONFIG_CHANGE 1305 /* Audit system configuration change */ |
84 | #define AUDIT_SOCKADDR 1306 /* sockaddr copied as syscall arg */ | 84 | #define AUDIT_SOCKADDR 1306 /* sockaddr copied as syscall arg */ |
85 | #define AUDIT_CWD 1307 /* Current working directory */ | 85 | #define AUDIT_CWD 1307 /* Current working directory */ |
86 | #define AUDIT_EXECVE 1309 /* execve arguments */ | ||
86 | #define AUDIT_IPC_SET_PERM 1311 /* IPC new permissions record type */ | 87 | #define AUDIT_IPC_SET_PERM 1311 /* IPC new permissions record type */ |
87 | 88 | ||
88 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ | 89 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ |
@@ -283,6 +284,7 @@ struct audit_buffer; | |||
283 | struct audit_context; | 284 | struct audit_context; |
284 | struct inode; | 285 | struct inode; |
285 | struct netlink_skb_parms; | 286 | struct netlink_skb_parms; |
287 | struct linux_binprm; | ||
286 | 288 | ||
287 | #define AUDITSC_INVALID 0 | 289 | #define AUDITSC_INVALID 0 |
288 | #define AUDITSC_SUCCESS 1 | 290 | #define AUDITSC_SUCCESS 1 |
@@ -322,6 +324,7 @@ extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid); | |||
322 | extern uid_t audit_get_loginuid(struct audit_context *ctx); | 324 | extern uid_t audit_get_loginuid(struct audit_context *ctx); |
323 | extern int audit_ipc_obj(struct kern_ipc_perm *ipcp); | 325 | extern int audit_ipc_obj(struct kern_ipc_perm *ipcp); |
324 | extern int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp); | 326 | extern int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp); |
327 | extern int audit_bprm(struct linux_binprm *bprm); | ||
325 | extern int audit_socketcall(int nargs, unsigned long *args); | 328 | extern int audit_socketcall(int nargs, unsigned long *args); |
326 | extern int audit_sockaddr(int len, void *addr); | 329 | extern int audit_sockaddr(int len, void *addr); |
327 | extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); | 330 | extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); |
@@ -342,6 +345,7 @@ extern int audit_set_macxattr(const char *name); | |||
342 | #define audit_get_loginuid(c) ({ -1; }) | 345 | #define audit_get_loginuid(c) ({ -1; }) |
343 | #define audit_ipc_obj(i) ({ 0; }) | 346 | #define audit_ipc_obj(i) ({ 0; }) |
344 | #define audit_ipc_set_perm(q,u,g,m,i) ({ 0; }) | 347 | #define audit_ipc_set_perm(q,u,g,m,i) ({ 0; }) |
348 | #define audit_bprm(p) ({ 0; }) | ||
345 | #define audit_socketcall(n,a) ({ 0; }) | 349 | #define audit_socketcall(n,a) ({ 0; }) |
346 | #define audit_sockaddr(len, addr) ({ 0; }) | 350 | #define audit_sockaddr(len, addr) ({ 0; }) |
347 | #define audit_avc_path(dentry, mnt) ({ 0; }) | 351 | #define audit_avc_path(dentry, mnt) ({ 0; }) |
@@ -364,7 +368,7 @@ extern void audit_log_end(struct audit_buffer *ab); | |||
364 | extern void audit_log_hex(struct audit_buffer *ab, | 368 | extern void audit_log_hex(struct audit_buffer *ab, |
365 | const unsigned char *buf, | 369 | const unsigned char *buf, |
366 | size_t len); | 370 | size_t len); |
367 | extern void audit_log_untrustedstring(struct audit_buffer *ab, | 371 | extern const char * audit_log_untrustedstring(struct audit_buffer *ab, |
368 | const char *string); | 372 | const char *string); |
369 | extern void audit_log_d_path(struct audit_buffer *ab, | 373 | extern void audit_log_d_path(struct audit_buffer *ab, |
370 | const char *prefix, | 374 | const char *prefix, |
diff --git a/kernel/audit.c b/kernel/audit.c index bf74bf02aa4b..d09f131b111a 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -1026,18 +1026,20 @@ void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, | |||
1026 | * or a space. Unescaped strings will start and end with a double quote mark. | 1026 | * or a space. Unescaped strings will start and end with a double quote mark. |
1027 | * Strings that are escaped are printed in hex (2 digits per char). | 1027 | * Strings that are escaped are printed in hex (2 digits per char). |
1028 | */ | 1028 | */ |
1029 | void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) | 1029 | const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string) |
1030 | { | 1030 | { |
1031 | const unsigned char *p = string; | 1031 | const unsigned char *p = string; |
1032 | size_t len = strlen(string); | ||
1032 | 1033 | ||
1033 | while (*p) { | 1034 | while (*p) { |
1034 | if (*p == '"' || *p < 0x21 || *p > 0x7f) { | 1035 | if (*p == '"' || *p < 0x21 || *p > 0x7f) { |
1035 | audit_log_hex(ab, string, strlen(string)); | 1036 | audit_log_hex(ab, string, len); |
1036 | return; | 1037 | return string + len + 1; |
1037 | } | 1038 | } |
1038 | p++; | 1039 | p++; |
1039 | } | 1040 | } |
1040 | audit_log_format(ab, "\"%s\"", string); | 1041 | audit_log_format(ab, "\"%s\"", string); |
1042 | return p + 1; | ||
1041 | } | 1043 | } |
1042 | 1044 | ||
1043 | /* This is a helper-function to print the escaped d_path */ | 1045 | /* This is a helper-function to print the escaped d_path */ |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 1c03a4ed1b27..114f921979ec 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <linux/list.h> | 59 | #include <linux/list.h> |
60 | #include <linux/tty.h> | 60 | #include <linux/tty.h> |
61 | #include <linux/selinux.h> | 61 | #include <linux/selinux.h> |
62 | #include <linux/binfmts.h> | ||
62 | 63 | ||
63 | #include "audit.h" | 64 | #include "audit.h" |
64 | 65 | ||
@@ -110,6 +111,13 @@ struct audit_aux_data_ipcctl { | |||
110 | u32 osid; | 111 | u32 osid; |
111 | }; | 112 | }; |
112 | 113 | ||
114 | struct audit_aux_data_execve { | ||
115 | struct audit_aux_data d; | ||
116 | int argc; | ||
117 | int envc; | ||
118 | char mem[0]; | ||
119 | }; | ||
120 | |||
113 | struct audit_aux_data_socketcall { | 121 | struct audit_aux_data_socketcall { |
114 | struct audit_aux_data d; | 122 | struct audit_aux_data d; |
115 | int nargs; | 123 | int nargs; |
@@ -667,6 +675,16 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
667 | kfree(ctx); | 675 | kfree(ctx); |
668 | } | 676 | } |
669 | break; } | 677 | break; } |
678 | case AUDIT_EXECVE: { | ||
679 | struct audit_aux_data_execve *axi = (void *)aux; | ||
680 | int i; | ||
681 | const char *p; | ||
682 | for (i = 0, p = axi->mem; i < axi->argc; i++) { | ||
683 | audit_log_format(ab, "a%d=", i); | ||
684 | p = audit_log_untrustedstring(ab, p); | ||
685 | audit_log_format(ab, "\n"); | ||
686 | } | ||
687 | break; } | ||
670 | 688 | ||
671 | case AUDIT_SOCKETCALL: { | 689 | case AUDIT_SOCKETCALL: { |
672 | int i; | 690 | int i; |
@@ -1231,6 +1249,39 @@ int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, | |||
1231 | return 0; | 1249 | return 0; |
1232 | } | 1250 | } |
1233 | 1251 | ||
1252 | int audit_bprm(struct linux_binprm *bprm) | ||
1253 | { | ||
1254 | struct audit_aux_data_execve *ax; | ||
1255 | struct audit_context *context = current->audit_context; | ||
1256 | unsigned long p, next; | ||
1257 | void *to; | ||
1258 | |||
1259 | if (likely(!audit_enabled || !context)) | ||
1260 | return 0; | ||
1261 | |||
1262 | ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p, | ||
1263 | GFP_KERNEL); | ||
1264 | if (!ax) | ||
1265 | return -ENOMEM; | ||
1266 | |||
1267 | ax->argc = bprm->argc; | ||
1268 | ax->envc = bprm->envc; | ||
1269 | for (p = bprm->p, to = ax->mem; p < MAX_ARG_PAGES*PAGE_SIZE; p = next) { | ||
1270 | struct page *page = bprm->page[p / PAGE_SIZE]; | ||
1271 | void *kaddr = kmap(page); | ||
1272 | next = (p + PAGE_SIZE) & ~(PAGE_SIZE - 1); | ||
1273 | memcpy(to, kaddr + (p & (PAGE_SIZE - 1)), next - p); | ||
1274 | to += next - p; | ||
1275 | kunmap(page); | ||
1276 | } | ||
1277 | |||
1278 | ax->d.type = AUDIT_EXECVE; | ||
1279 | ax->d.next = context->aux; | ||
1280 | context->aux = (void *)ax; | ||
1281 | return 0; | ||
1282 | } | ||
1283 | |||
1284 | |||
1234 | /** | 1285 | /** |
1235 | * audit_socketcall - record audit data for sys_socketcall | 1286 | * audit_socketcall - record audit data for sys_socketcall |
1236 | * @nargs: number of args | 1287 | * @nargs: number of args |