diff options
| -rw-r--r-- | fs/pipe.c | 7 | ||||
| -rw-r--r-- | include/linux/audit.h | 9 | ||||
| -rw-r--r-- | kernel/audit.c | 216 | ||||
| -rw-r--r-- | kernel/auditfilter.c | 9 | ||||
| -rw-r--r-- | kernel/auditsc.c | 40 | ||||
| -rw-r--r-- | net/socket.c | 52 |
6 files changed, 257 insertions, 76 deletions
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/uio.h> | 16 | #include <linux/uio.h> |
| 17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
| 18 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
| 19 | #include <linux/audit.h> | ||
| 19 | 20 | ||
| 20 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
| 21 | #include <asm/ioctls.h> | 22 | #include <asm/ioctls.h> |
| @@ -985,6 +986,10 @@ int do_pipe(int *fd) | |||
| 985 | goto err_fdr; | 986 | goto err_fdr; |
| 986 | fdw = error; | 987 | fdw = error; |
| 987 | 988 | ||
| 989 | error = audit_fd_pair(fdr, fdw); | ||
| 990 | if (error < 0) | ||
| 991 | goto err_fdw; | ||
| 992 | |||
| 988 | fd_install(fdr, fr); | 993 | fd_install(fdr, fr); |
| 989 | fd_install(fdw, fw); | 994 | fd_install(fdw, fw); |
| 990 | fd[0] = fdr; | 995 | fd[0] = fdr; |
| @@ -992,6 +997,8 @@ int do_pipe(int *fd) | |||
| 992 | 997 | ||
| 993 | return 0; | 998 | return 0; |
| 994 | 999 | ||
| 1000 | err_fdw: | ||
| 1001 | put_unused_fd(fdw); | ||
| 995 | err_fdr: | 1002 | err_fdr: |
| 996 | put_unused_fd(fdr); | 1003 | put_unused_fd(fdr); |
| 997 | err_read_pipe: | 1004 | err_read_pipe: |
diff --git a/include/linux/audit.h b/include/linux/audit.h index 0e07db6cc0d0..229fa012c893 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
| @@ -89,6 +89,7 @@ | |||
| 89 | #define AUDIT_MQ_NOTIFY 1314 /* POSIX MQ notify record type */ | 89 | #define AUDIT_MQ_NOTIFY 1314 /* POSIX MQ notify record type */ |
| 90 | #define AUDIT_MQ_GETSETATTR 1315 /* POSIX MQ get/set attribute record type */ | 90 | #define AUDIT_MQ_GETSETATTR 1315 /* POSIX MQ get/set attribute record type */ |
| 91 | #define AUDIT_KERNEL_OTHER 1316 /* For use by 3rd party modules */ | 91 | #define AUDIT_KERNEL_OTHER 1316 /* For use by 3rd party modules */ |
| 92 | #define AUDIT_FD_PAIR 1317 /* audit record for pipe/socketpair */ | ||
| 92 | 93 | ||
| 93 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ | 94 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ |
| 94 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ | 95 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ |
| @@ -387,6 +388,7 @@ extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode | |||
| 387 | extern int audit_bprm(struct linux_binprm *bprm); | 388 | extern int audit_bprm(struct linux_binprm *bprm); |
| 388 | extern int audit_socketcall(int nargs, unsigned long *args); | 389 | extern int audit_socketcall(int nargs, unsigned long *args); |
| 389 | extern int audit_sockaddr(int len, void *addr); | 390 | extern int audit_sockaddr(int len, void *addr); |
| 391 | extern int __audit_fd_pair(int fd1, int fd2); | ||
| 390 | extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); | 392 | extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt); |
| 391 | extern int audit_set_macxattr(const char *name); | 393 | extern int audit_set_macxattr(const char *name); |
| 392 | extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr); | 394 | extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr); |
| @@ -401,6 +403,12 @@ static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp) | |||
| 401 | return __audit_ipc_obj(ipcp); | 403 | return __audit_ipc_obj(ipcp); |
| 402 | return 0; | 404 | return 0; |
| 403 | } | 405 | } |
| 406 | static inline int audit_fd_pair(int fd1, int fd2) | ||
| 407 | { | ||
| 408 | if (unlikely(!audit_dummy_context())) | ||
| 409 | return __audit_fd_pair(fd1, fd2); | ||
| 410 | return 0; | ||
| 411 | } | ||
| 404 | static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) | 412 | static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) |
| 405 | { | 413 | { |
| 406 | if (unlikely(!audit_dummy_context())) | 414 | if (unlikely(!audit_dummy_context())) |
| @@ -459,6 +467,7 @@ extern int audit_n_rules; | |||
| 459 | #define audit_ipc_set_perm(q,u,g,m) ({ 0; }) | 467 | #define audit_ipc_set_perm(q,u,g,m) ({ 0; }) |
| 460 | #define audit_bprm(p) ({ 0; }) | 468 | #define audit_bprm(p) ({ 0; }) |
| 461 | #define audit_socketcall(n,a) ({ 0; }) | 469 | #define audit_socketcall(n,a) ({ 0; }) |
| 470 | #define audit_fd_pair(n,a) ({ 0; }) | ||
| 462 | #define audit_sockaddr(len, addr) ({ 0; }) | 471 | #define audit_sockaddr(len, addr) ({ 0; }) |
| 463 | #define audit_avc_path(dentry, mnt) ({ 0; }) | 472 | #define audit_avc_path(dentry, mnt) ({ 0; }) |
| 464 | #define audit_set_macxattr(n) do { ; } while (0) | 473 | #define audit_set_macxattr(n) do { ; } while (0) |
diff --git a/kernel/audit.c b/kernel/audit.c index d9b690ac684b..76c9a11b72d6 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * Gateway between the kernel (e.g., selinux) and the user-space audit daemon. | 2 | * Gateway between the kernel (e.g., selinux) and the user-space audit daemon. |
| 3 | * System-call specific features have moved to auditsc.c | 3 | * System-call specific features have moved to auditsc.c |
| 4 | * | 4 | * |
| 5 | * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. | 5 | * Copyright 2003-2007 Red Hat Inc., Durham, North Carolina. |
| 6 | * All Rights Reserved. | 6 | * All Rights Reserved. |
| 7 | * | 7 | * |
| 8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| @@ -65,7 +65,9 @@ | |||
| 65 | * (Initialization happens after skb_init is called.) */ | 65 | * (Initialization happens after skb_init is called.) */ |
| 66 | static int audit_initialized; | 66 | static int audit_initialized; |
| 67 | 67 | ||
| 68 | /* No syscall auditing will take place unless audit_enabled != 0. */ | 68 | /* 0 - no auditing |
| 69 | * 1 - auditing enabled | ||
| 70 | * 2 - auditing enabled and configuration is locked/unchangeable. */ | ||
| 69 | int audit_enabled; | 71 | int audit_enabled; |
| 70 | 72 | ||
| 71 | /* Default state when kernel boots without any parameters. */ | 73 | /* Default state when kernel boots without any parameters. */ |
| @@ -239,102 +241,150 @@ void audit_log_lost(const char *message) | |||
| 239 | 241 | ||
| 240 | static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid) | 242 | static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid) |
| 241 | { | 243 | { |
| 242 | int old = audit_rate_limit; | 244 | int res, rc = 0, old = audit_rate_limit; |
| 245 | |||
| 246 | /* check if we are locked */ | ||
| 247 | if (audit_enabled == 2) | ||
| 248 | res = 0; | ||
| 249 | else | ||
| 250 | res = 1; | ||
| 243 | 251 | ||
| 244 | if (sid) { | 252 | if (sid) { |
| 245 | char *ctx = NULL; | 253 | char *ctx = NULL; |
| 246 | u32 len; | 254 | u32 len; |
| 247 | int rc; | 255 | if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { |
| 248 | if ((rc = selinux_sid_to_string(sid, &ctx, &len))) | ||
| 249 | return rc; | ||
| 250 | else | ||
| 251 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | 256 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
| 252 | "audit_rate_limit=%d old=%d by auid=%u subj=%s", | 257 | "audit_rate_limit=%d old=%d by auid=%u" |
| 253 | limit, old, loginuid, ctx); | 258 | " subj=%s res=%d", |
| 254 | kfree(ctx); | 259 | limit, old, loginuid, ctx, res); |
| 255 | } else | 260 | kfree(ctx); |
| 256 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | 261 | } else |
| 257 | "audit_rate_limit=%d old=%d by auid=%u", | 262 | res = 0; /* Something weird, deny request */ |
| 258 | limit, old, loginuid); | 263 | } |
| 259 | audit_rate_limit = limit; | 264 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
| 260 | return 0; | 265 | "audit_rate_limit=%d old=%d by auid=%u res=%d", |
| 266 | limit, old, loginuid, res); | ||
| 267 | |||
| 268 | /* If we are allowed, make the change */ | ||
| 269 | if (res == 1) | ||
| 270 | audit_rate_limit = limit; | ||
| 271 | /* Not allowed, update reason */ | ||
| 272 | else if (rc == 0) | ||
| 273 | rc = -EPERM; | ||
| 274 | return rc; | ||
| 261 | } | 275 | } |
| 262 | 276 | ||
| 263 | static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid) | 277 | static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid) |
| 264 | { | 278 | { |
| 265 | int old = audit_backlog_limit; | 279 | int res, rc = 0, old = audit_backlog_limit; |
| 280 | |||
| 281 | /* check if we are locked */ | ||
| 282 | if (audit_enabled == 2) | ||
| 283 | res = 0; | ||
| 284 | else | ||
| 285 | res = 1; | ||
| 266 | 286 | ||
| 267 | if (sid) { | 287 | if (sid) { |
| 268 | char *ctx = NULL; | 288 | char *ctx = NULL; |
| 269 | u32 len; | 289 | u32 len; |
| 270 | int rc; | 290 | if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { |
| 271 | if ((rc = selinux_sid_to_string(sid, &ctx, &len))) | ||
| 272 | return rc; | ||
| 273 | else | ||
| 274 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | 291 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
| 275 | "audit_backlog_limit=%d old=%d by auid=%u subj=%s", | 292 | "audit_backlog_limit=%d old=%d by auid=%u" |
| 276 | limit, old, loginuid, ctx); | 293 | " subj=%s res=%d", |
| 277 | kfree(ctx); | 294 | limit, old, loginuid, ctx, res); |
| 278 | } else | 295 | kfree(ctx); |
| 279 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | 296 | } else |
| 280 | "audit_backlog_limit=%d old=%d by auid=%u", | 297 | res = 0; /* Something weird, deny request */ |
| 281 | limit, old, loginuid); | 298 | } |
| 282 | audit_backlog_limit = limit; | 299 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
| 283 | return 0; | 300 | "audit_backlog_limit=%d old=%d by auid=%u res=%d", |
| 301 | limit, old, loginuid, res); | ||
| 302 | |||
| 303 | /* If we are allowed, make the change */ | ||
| 304 | if (res == 1) | ||
| 305 | audit_backlog_limit = limit; | ||
| 306 | /* Not allowed, update reason */ | ||
| 307 | else if (rc == 0) | ||
| 308 | rc = -EPERM; | ||
| 309 | return rc; | ||
| 284 | } | 310 | } |
| 285 | 311 | ||
| 286 | static int audit_set_enabled(int state, uid_t loginuid, u32 sid) | 312 | static int audit_set_enabled(int state, uid_t loginuid, u32 sid) |
| 287 | { | 313 | { |
| 288 | int old = audit_enabled; | 314 | int res, rc = 0, old = audit_enabled; |
| 289 | 315 | ||
| 290 | if (state != 0 && state != 1) | 316 | if (state < 0 || state > 2) |
| 291 | return -EINVAL; | 317 | return -EINVAL; |
| 292 | 318 | ||
| 319 | /* check if we are locked */ | ||
| 320 | if (audit_enabled == 2) | ||
| 321 | res = 0; | ||
| 322 | else | ||
| 323 | res = 1; | ||
| 324 | |||
| 293 | if (sid) { | 325 | if (sid) { |
| 294 | char *ctx = NULL; | 326 | char *ctx = NULL; |
| 295 | u32 len; | 327 | u32 len; |
| 296 | int rc; | 328 | if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { |
| 297 | if ((rc = selinux_sid_to_string(sid, &ctx, &len))) | ||
| 298 | return rc; | ||
| 299 | else | ||
| 300 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | 329 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
| 301 | "audit_enabled=%d old=%d by auid=%u subj=%s", | 330 | "audit_enabled=%d old=%d by auid=%u" |
| 302 | state, old, loginuid, ctx); | 331 | " subj=%s res=%d", |
| 303 | kfree(ctx); | 332 | state, old, loginuid, ctx, res); |
| 304 | } else | 333 | kfree(ctx); |
| 305 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | 334 | } else |
| 306 | "audit_enabled=%d old=%d by auid=%u", | 335 | res = 0; /* Something weird, deny request */ |
| 307 | state, old, loginuid); | 336 | } |
| 308 | audit_enabled = state; | 337 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
| 309 | return 0; | 338 | "audit_enabled=%d old=%d by auid=%u res=%d", |
| 339 | state, old, loginuid, res); | ||
| 340 | |||
| 341 | /* If we are allowed, make the change */ | ||
| 342 | if (res == 1) | ||
| 343 | audit_enabled = state; | ||
| 344 | /* Not allowed, update reason */ | ||
| 345 | else if (rc == 0) | ||
| 346 | rc = -EPERM; | ||
| 347 | return rc; | ||
| 310 | } | 348 | } |
| 311 | 349 | ||
| 312 | static int audit_set_failure(int state, uid_t loginuid, u32 sid) | 350 | static int audit_set_failure(int state, uid_t loginuid, u32 sid) |
| 313 | { | 351 | { |
| 314 | int old = audit_failure; | 352 | int res, rc = 0, old = audit_failure; |
| 315 | 353 | ||
| 316 | if (state != AUDIT_FAIL_SILENT | 354 | if (state != AUDIT_FAIL_SILENT |
| 317 | && state != AUDIT_FAIL_PRINTK | 355 | && state != AUDIT_FAIL_PRINTK |
| 318 | && state != AUDIT_FAIL_PANIC) | 356 | && state != AUDIT_FAIL_PANIC) |
| 319 | return -EINVAL; | 357 | return -EINVAL; |
| 320 | 358 | ||
| 359 | /* check if we are locked */ | ||
| 360 | if (audit_enabled == 2) | ||
| 361 | res = 0; | ||
| 362 | else | ||
| 363 | res = 1; | ||
| 364 | |||
| 321 | if (sid) { | 365 | if (sid) { |
| 322 | char *ctx = NULL; | 366 | char *ctx = NULL; |
| 323 | u32 len; | 367 | u32 len; |
| 324 | int rc; | 368 | if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { |
| 325 | if ((rc = selinux_sid_to_string(sid, &ctx, &len))) | ||
| 326 | return rc; | ||
| 327 | else | ||
| 328 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | 369 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
| 329 | "audit_failure=%d old=%d by auid=%u subj=%s", | 370 | "audit_failure=%d old=%d by auid=%u" |
| 330 | state, old, loginuid, ctx); | 371 | " subj=%s res=%d", |
| 331 | kfree(ctx); | 372 | state, old, loginuid, ctx, res); |
| 332 | } else | 373 | kfree(ctx); |
| 333 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, | 374 | } else |
| 334 | "audit_failure=%d old=%d by auid=%u", | 375 | res = 0; /* Something weird, deny request */ |
| 335 | state, old, loginuid); | 376 | } |
| 336 | audit_failure = state; | 377 | audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, |
| 337 | return 0; | 378 | "audit_failure=%d old=%d by auid=%u res=%d", |
| 379 | state, old, loginuid, res); | ||
| 380 | |||
| 381 | /* If we are allowed, make the change */ | ||
| 382 | if (res == 1) | ||
| 383 | audit_failure = state; | ||
| 384 | /* Not allowed, update reason */ | ||
| 385 | else if (rc == 0) | ||
| 386 | rc = -EPERM; | ||
| 387 | return rc; | ||
| 338 | } | 388 | } |
| 339 | 389 | ||
| 340 | static int kauditd_thread(void *dummy) | 390 | static int kauditd_thread(void *dummy) |
| @@ -599,6 +649,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 599 | case AUDIT_DEL: | 649 | case AUDIT_DEL: |
| 600 | if (nlmsg_len(nlh) < sizeof(struct audit_rule)) | 650 | if (nlmsg_len(nlh) < sizeof(struct audit_rule)) |
| 601 | return -EINVAL; | 651 | return -EINVAL; |
| 652 | if (audit_enabled == 2) { | ||
| 653 | ab = audit_log_start(NULL, GFP_KERNEL, | ||
| 654 | AUDIT_CONFIG_CHANGE); | ||
| 655 | if (ab) { | ||
| 656 | audit_log_format(ab, | ||
| 657 | "pid=%d uid=%u auid=%u", | ||
| 658 | pid, uid, loginuid); | ||
| 659 | if (sid) { | ||
| 660 | if (selinux_sid_to_string( | ||
| 661 | sid, &ctx, &len)) { | ||
| 662 | audit_log_format(ab, | ||
| 663 | " ssid=%u", sid); | ||
| 664 | /* Maybe call audit_panic? */ | ||
| 665 | } else | ||
| 666 | audit_log_format(ab, | ||
| 667 | " subj=%s", ctx); | ||
| 668 | kfree(ctx); | ||
| 669 | } | ||
| 670 | audit_log_format(ab, " audit_enabled=%d res=0", | ||
| 671 | audit_enabled); | ||
| 672 | audit_log_end(ab); | ||
| 673 | } | ||
| 674 | return -EPERM; | ||
| 675 | } | ||
| 602 | /* fallthrough */ | 676 | /* fallthrough */ |
| 603 | case AUDIT_LIST: | 677 | case AUDIT_LIST: |
| 604 | err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, | 678 | err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, |
| @@ -609,6 +683,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 609 | case AUDIT_DEL_RULE: | 683 | case AUDIT_DEL_RULE: |
| 610 | if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) | 684 | if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) |
| 611 | return -EINVAL; | 685 | return -EINVAL; |
| 686 | if (audit_enabled == 2) { | ||
| 687 | ab = audit_log_start(NULL, GFP_KERNEL, | ||
| 688 | AUDIT_CONFIG_CHANGE); | ||
| 689 | if (ab) { | ||
| 690 | audit_log_format(ab, | ||
| 691 | "pid=%d uid=%u auid=%u", | ||
| 692 | pid, uid, loginuid); | ||
| 693 | if (sid) { | ||
| 694 | if (selinux_sid_to_string( | ||
| 695 | sid, &ctx, &len)) { | ||
| 696 | audit_log_format(ab, | ||
| 697 | " ssid=%u", sid); | ||
| 698 | /* Maybe call audit_panic? */ | ||
| 699 | } else | ||
| 700 | audit_log_format(ab, | ||
| 701 | " subj=%s", ctx); | ||
| 702 | kfree(ctx); | ||
| 703 | } | ||
| 704 | audit_log_format(ab, " audit_enabled=%d res=0", | ||
| 705 | audit_enabled); | ||
| 706 | audit_log_end(ab); | ||
| 707 | } | ||
| 708 | return -EPERM; | ||
| 709 | } | ||
| 612 | /* fallthrough */ | 710 | /* fallthrough */ |
| 613 | case AUDIT_LIST_RULES: | 711 | case AUDIT_LIST_RULES: |
| 614 | err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, | 712 | err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 87865f8b4ce3..3749193aed8c 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -937,9 +937,10 @@ static void audit_update_watch(struct audit_parent *parent, | |||
| 937 | } | 937 | } |
| 938 | 938 | ||
| 939 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 939 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
| 940 | audit_log_format(ab, "audit updated rules specifying path="); | 940 | audit_log_format(ab, "op=updated rules specifying path="); |
| 941 | audit_log_untrustedstring(ab, owatch->path); | 941 | audit_log_untrustedstring(ab, owatch->path); |
| 942 | audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino); | 942 | audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino); |
| 943 | audit_log_format(ab, " list=%d res=1", r->listnr); | ||
| 943 | audit_log_end(ab); | 944 | audit_log_end(ab); |
| 944 | 945 | ||
| 945 | audit_remove_watch(owatch); | 946 | audit_remove_watch(owatch); |
| @@ -969,14 +970,14 @@ static void audit_remove_parent_watches(struct audit_parent *parent) | |||
| 969 | e = container_of(r, struct audit_entry, rule); | 970 | e = container_of(r, struct audit_entry, rule); |
| 970 | 971 | ||
| 971 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 972 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
| 972 | audit_log_format(ab, "audit implicitly removed rule path="); | 973 | audit_log_format(ab, "op=remove rule path="); |
| 973 | audit_log_untrustedstring(ab, w->path); | 974 | audit_log_untrustedstring(ab, w->path); |
| 974 | if (r->filterkey) { | 975 | if (r->filterkey) { |
| 975 | audit_log_format(ab, " key="); | 976 | audit_log_format(ab, " key="); |
| 976 | audit_log_untrustedstring(ab, r->filterkey); | 977 | audit_log_untrustedstring(ab, r->filterkey); |
| 977 | } else | 978 | } else |
| 978 | audit_log_format(ab, " key=(null)"); | 979 | audit_log_format(ab, " key=(null)"); |
| 979 | audit_log_format(ab, " list=%d", r->listnr); | 980 | audit_log_format(ab, " list=%d res=1", r->listnr); |
| 980 | audit_log_end(ab); | 981 | audit_log_end(ab); |
| 981 | 982 | ||
| 982 | list_del(&r->rlist); | 983 | list_del(&r->rlist); |
| @@ -1410,7 +1411,7 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action, | |||
| 1410 | audit_log_format(ab, " subj=%s", ctx); | 1411 | audit_log_format(ab, " subj=%s", ctx); |
| 1411 | kfree(ctx); | 1412 | kfree(ctx); |
| 1412 | } | 1413 | } |
| 1413 | audit_log_format(ab, " %s rule key=", action); | 1414 | audit_log_format(ab, " op=%s rule key=", action); |
| 1414 | if (rule->filterkey) | 1415 | if (rule->filterkey) |
| 1415 | audit_log_untrustedstring(ab, rule->filterkey); | 1416 | audit_log_untrustedstring(ab, rule->filterkey); |
| 1416 | else | 1417 | else |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 298897559ca4..359955800dd2 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -170,6 +170,11 @@ struct audit_aux_data_sockaddr { | |||
| 170 | char a[0]; | 170 | char a[0]; |
| 171 | }; | 171 | }; |
| 172 | 172 | ||
| 173 | struct audit_aux_data_fd_pair { | ||
| 174 | struct audit_aux_data d; | ||
| 175 | int fd[2]; | ||
| 176 | }; | ||
| 177 | |||
| 173 | struct audit_aux_data_path { | 178 | struct audit_aux_data_path { |
| 174 | struct audit_aux_data d; | 179 | struct audit_aux_data d; |
| 175 | struct dentry *dentry; | 180 | struct dentry *dentry; |
| @@ -961,6 +966,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 961 | audit_log_d_path(ab, "path=", axi->dentry, axi->mnt); | 966 | audit_log_d_path(ab, "path=", axi->dentry, axi->mnt); |
| 962 | break; } | 967 | break; } |
| 963 | 968 | ||
| 969 | case AUDIT_FD_PAIR: { | ||
| 970 | struct audit_aux_data_fd_pair *axs = (void *)aux; | ||
| 971 | audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]); | ||
| 972 | break; } | ||
| 973 | |||
| 964 | } | 974 | } |
| 965 | audit_log_end(ab); | 975 | audit_log_end(ab); |
| 966 | } | 976 | } |
| @@ -1815,6 +1825,36 @@ int audit_socketcall(int nargs, unsigned long *args) | |||
| 1815 | } | 1825 | } |
| 1816 | 1826 | ||
| 1817 | /** | 1827 | /** |
| 1828 | * __audit_fd_pair - record audit data for pipe and socketpair | ||
| 1829 | * @fd1: the first file descriptor | ||
| 1830 | * @fd2: the second file descriptor | ||
| 1831 | * | ||
| 1832 | * Returns 0 for success or NULL context or < 0 on error. | ||
| 1833 | */ | ||
| 1834 | int __audit_fd_pair(int fd1, int fd2) | ||
| 1835 | { | ||
| 1836 | struct audit_context *context = current->audit_context; | ||
| 1837 | struct audit_aux_data_fd_pair *ax; | ||
| 1838 | |||
| 1839 | if (likely(!context)) { | ||
| 1840 | return 0; | ||
| 1841 | } | ||
| 1842 | |||
| 1843 | ax = kmalloc(sizeof(*ax), GFP_KERNEL); | ||
| 1844 | if (!ax) { | ||
| 1845 | return -ENOMEM; | ||
| 1846 | } | ||
| 1847 | |||
| 1848 | ax->fd[0] = fd1; | ||
| 1849 | ax->fd[1] = fd2; | ||
| 1850 | |||
| 1851 | ax->d.type = AUDIT_FD_PAIR; | ||
| 1852 | ax->d.next = context->aux; | ||
| 1853 | context->aux = (void *)ax; | ||
| 1854 | return 0; | ||
| 1855 | } | ||
| 1856 | |||
| 1857 | /** | ||
| 1818 | * audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto | 1858 | * audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto |
| 1819 | * @len: data length in user space | 1859 | * @len: data length in user space |
| 1820 | * @a: data address in kernel space | 1860 | * @a: data address in kernel space |
diff --git a/net/socket.c b/net/socket.c index 0778c5442411..9566e57ac7f5 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -1194,6 +1194,7 @@ asmlinkage long sys_socketpair(int family, int type, int protocol, | |||
| 1194 | { | 1194 | { |
| 1195 | struct socket *sock1, *sock2; | 1195 | struct socket *sock1, *sock2; |
| 1196 | int fd1, fd2, err; | 1196 | int fd1, fd2, err; |
| 1197 | struct file *newfile1, *newfile2; | ||
| 1197 | 1198 | ||
| 1198 | /* | 1199 | /* |
| 1199 | * Obtain the first socket and check if the underlying protocol | 1200 | * Obtain the first socket and check if the underlying protocol |
| @@ -1212,18 +1213,37 @@ asmlinkage long sys_socketpair(int family, int type, int protocol, | |||
| 1212 | if (err < 0) | 1213 | if (err < 0) |
| 1213 | goto out_release_both; | 1214 | goto out_release_both; |
| 1214 | 1215 | ||
| 1215 | fd1 = fd2 = -1; | 1216 | fd1 = sock_alloc_fd(&newfile1); |
| 1217 | if (unlikely(fd1 < 0)) | ||
| 1218 | goto out_release_both; | ||
| 1216 | 1219 | ||
| 1217 | err = sock_map_fd(sock1); | 1220 | fd2 = sock_alloc_fd(&newfile2); |
| 1218 | if (err < 0) | 1221 | if (unlikely(fd2 < 0)) { |
| 1222 | put_filp(newfile1); | ||
| 1223 | put_unused_fd(fd1); | ||
| 1219 | goto out_release_both; | 1224 | goto out_release_both; |
| 1220 | fd1 = err; | 1225 | } |
| 1221 | 1226 | ||
| 1222 | err = sock_map_fd(sock2); | 1227 | err = sock_attach_fd(sock1, newfile1); |
| 1223 | if (err < 0) | 1228 | if (unlikely(err < 0)) { |
| 1224 | goto out_close_1; | 1229 | goto out_fd2; |
| 1225 | fd2 = err; | 1230 | } |
| 1231 | |||
| 1232 | err = sock_attach_fd(sock2, newfile2); | ||
| 1233 | if (unlikely(err < 0)) { | ||
| 1234 | fput(newfile1); | ||
| 1235 | goto out_fd1; | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | err = audit_fd_pair(fd1, fd2); | ||
| 1239 | if (err < 0) { | ||
| 1240 | fput(newfile1); | ||
| 1241 | fput(newfile2); | ||
| 1242 | goto out_fd; | ||
| 1243 | } | ||
| 1226 | 1244 | ||
| 1245 | fd_install(fd1, newfile1); | ||
| 1246 | fd_install(fd2, newfile2); | ||
| 1227 | /* fd1 and fd2 may be already another descriptors. | 1247 | /* fd1 and fd2 may be already another descriptors. |
| 1228 | * Not kernel problem. | 1248 | * Not kernel problem. |
| 1229 | */ | 1249 | */ |
| @@ -1238,17 +1258,23 @@ asmlinkage long sys_socketpair(int family, int type, int protocol, | |||
| 1238 | sys_close(fd1); | 1258 | sys_close(fd1); |
| 1239 | return err; | 1259 | return err; |
| 1240 | 1260 | ||
| 1241 | out_close_1: | ||
| 1242 | sock_release(sock2); | ||
| 1243 | sys_close(fd1); | ||
| 1244 | return err; | ||
| 1245 | |||
| 1246 | out_release_both: | 1261 | out_release_both: |
| 1247 | sock_release(sock2); | 1262 | sock_release(sock2); |
| 1248 | out_release_1: | 1263 | out_release_1: |
| 1249 | sock_release(sock1); | 1264 | sock_release(sock1); |
| 1250 | out: | 1265 | out: |
| 1251 | return err; | 1266 | return err; |
| 1267 | |||
| 1268 | out_fd2: | ||
| 1269 | put_filp(newfile1); | ||
| 1270 | sock_release(sock1); | ||
| 1271 | out_fd1: | ||
| 1272 | put_filp(newfile2); | ||
| 1273 | sock_release(sock2); | ||
| 1274 | out_fd: | ||
| 1275 | put_unused_fd(fd1); | ||
| 1276 | put_unused_fd(fd2); | ||
| 1277 | goto out; | ||
| 1252 | } | 1278 | } |
| 1253 | 1279 | ||
| 1254 | /* | 1280 | /* |
