diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/Makefile | 2 | ||||
-rw-r--r-- | kernel/audit.c | 112 | ||||
-rw-r--r-- | kernel/auditsc.c | 47 | ||||
-rw-r--r-- | kernel/exit.c | 15 | ||||
-rw-r--r-- | kernel/futex.c | 3 | ||||
-rw-r--r-- | kernel/itimer.c | 6 | ||||
-rw-r--r-- | kernel/kallsyms.c | 13 | ||||
-rw-r--r-- | kernel/kprobes.c | 142 | ||||
-rw-r--r-- | kernel/kthread.c | 2 | ||||
-rw-r--r-- | kernel/module.c | 2 | ||||
-rw-r--r-- | kernel/panic.c | 4 | ||||
-rw-r--r-- | kernel/power/swsusp.c | 2 | ||||
-rw-r--r-- | kernel/printk.c | 27 | ||||
-rw-r--r-- | kernel/profile.c | 4 | ||||
-rw-r--r-- | kernel/ptrace.c | 5 | ||||
-rw-r--r-- | kernel/rcupdate.c | 22 | ||||
-rw-r--r-- | kernel/sched.c | 28 | ||||
-rw-r--r-- | kernel/signal.c | 9 | ||||
-rw-r--r-- | kernel/stop_machine.c | 10 | ||||
-rw-r--r-- | kernel/sys.c | 27 | ||||
-rw-r--r-- | kernel/sys_ni.c | 1 | ||||
-rw-r--r-- | kernel/sysctl.c | 2 | ||||
-rw-r--r-- | kernel/time.c | 8 | ||||
-rw-r--r-- | kernel/timer.c | 2 |
24 files changed, 356 insertions, 139 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index eb88b446c2cc..b01d26fe8db7 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
@@ -29,7 +29,7 @@ obj-$(CONFIG_SYSFS) += ksysfs.o | |||
29 | obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ | 29 | obj-$(CONFIG_GENERIC_HARDIRQS) += irq/ |
30 | obj-$(CONFIG_SECCOMP) += seccomp.o | 30 | obj-$(CONFIG_SECCOMP) += seccomp.o |
31 | 31 | ||
32 | ifneq ($(CONFIG_IA64),y) | 32 | ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) |
33 | # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is | 33 | # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is |
34 | # needed for x86 only. Why this used to be enabled for all architectures is beyond | 34 | # needed for x86 only. Why this used to be enabled for all architectures is beyond |
35 | # me. I suspect most platforms don't need this, but until we know that for sure | 35 | # me. I suspect most platforms don't need this, but until we know that for sure |
diff --git a/kernel/audit.c b/kernel/audit.c index 0f84dd7af2c8..9c4f1af0c794 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* audit.c -- Auditing support -*- linux-c -*- | 1 | /* audit.c -- Auditing support |
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 | * |
@@ -38,7 +38,7 @@ | |||
38 | * 6) Support low-overhead kernel-based filtering to minimize the | 38 | * 6) Support low-overhead kernel-based filtering to minimize the |
39 | * information that must be passed to user-space. | 39 | * information that must be passed to user-space. |
40 | * | 40 | * |
41 | * Example user-space utilities: http://people.redhat.com/faith/audit/ | 41 | * Example user-space utilities: http://people.redhat.com/sgrubb/audit/ |
42 | */ | 42 | */ |
43 | 43 | ||
44 | #include <linux/init.h> | 44 | #include <linux/init.h> |
@@ -142,7 +142,6 @@ struct audit_buffer { | |||
142 | int total; | 142 | int total; |
143 | int type; | 143 | int type; |
144 | int pid; | 144 | int pid; |
145 | int count; /* Times requeued */ | ||
146 | }; | 145 | }; |
147 | 146 | ||
148 | void audit_set_type(struct audit_buffer *ab, int type) | 147 | void audit_set_type(struct audit_buffer *ab, int type) |
@@ -239,36 +238,36 @@ void audit_log_lost(const char *message) | |||
239 | 238 | ||
240 | } | 239 | } |
241 | 240 | ||
242 | static int audit_set_rate_limit(int limit) | 241 | static int audit_set_rate_limit(int limit, uid_t loginuid) |
243 | { | 242 | { |
244 | int old = audit_rate_limit; | 243 | int old = audit_rate_limit; |
245 | audit_rate_limit = limit; | 244 | audit_rate_limit = limit; |
246 | audit_log(current->audit_context, "audit_rate_limit=%d old=%d", | 245 | audit_log(NULL, "audit_rate_limit=%d old=%d by auid %u", |
247 | audit_rate_limit, old); | 246 | audit_rate_limit, old, loginuid); |
248 | return old; | 247 | return old; |
249 | } | 248 | } |
250 | 249 | ||
251 | static int audit_set_backlog_limit(int limit) | 250 | static int audit_set_backlog_limit(int limit, uid_t loginuid) |
252 | { | 251 | { |
253 | int old = audit_backlog_limit; | 252 | int old = audit_backlog_limit; |
254 | audit_backlog_limit = limit; | 253 | audit_backlog_limit = limit; |
255 | audit_log(current->audit_context, "audit_backlog_limit=%d old=%d", | 254 | audit_log(NULL, "audit_backlog_limit=%d old=%d by auid %u", |
256 | audit_backlog_limit, old); | 255 | audit_backlog_limit, old, loginuid); |
257 | return old; | 256 | return old; |
258 | } | 257 | } |
259 | 258 | ||
260 | static int audit_set_enabled(int state) | 259 | static int audit_set_enabled(int state, uid_t loginuid) |
261 | { | 260 | { |
262 | int old = audit_enabled; | 261 | int old = audit_enabled; |
263 | if (state != 0 && state != 1) | 262 | if (state != 0 && state != 1) |
264 | return -EINVAL; | 263 | return -EINVAL; |
265 | audit_enabled = state; | 264 | audit_enabled = state; |
266 | audit_log(current->audit_context, "audit_enabled=%d old=%d", | 265 | audit_log(NULL, "audit_enabled=%d old=%d by auid %u", |
267 | audit_enabled, old); | 266 | audit_enabled, old, loginuid); |
268 | return old; | 267 | return old; |
269 | } | 268 | } |
270 | 269 | ||
271 | static int audit_set_failure(int state) | 270 | static int audit_set_failure(int state, uid_t loginuid) |
272 | { | 271 | { |
273 | int old = audit_failure; | 272 | int old = audit_failure; |
274 | if (state != AUDIT_FAIL_SILENT | 273 | if (state != AUDIT_FAIL_SILENT |
@@ -276,8 +275,8 @@ static int audit_set_failure(int state) | |||
276 | && state != AUDIT_FAIL_PANIC) | 275 | && state != AUDIT_FAIL_PANIC) |
277 | return -EINVAL; | 276 | return -EINVAL; |
278 | audit_failure = state; | 277 | audit_failure = state; |
279 | audit_log(current->audit_context, "audit_failure=%d old=%d", | 278 | audit_log(NULL, "audit_failure=%d old=%d by auid %u", |
280 | audit_failure, old); | 279 | audit_failure, old, loginuid); |
281 | return old; | 280 | return old; |
282 | } | 281 | } |
283 | 282 | ||
@@ -344,6 +343,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
344 | int err; | 343 | int err; |
345 | struct audit_buffer *ab; | 344 | struct audit_buffer *ab; |
346 | u16 msg_type = nlh->nlmsg_type; | 345 | u16 msg_type = nlh->nlmsg_type; |
346 | uid_t loginuid; /* loginuid of sender */ | ||
347 | 347 | ||
348 | err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type); | 348 | err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type); |
349 | if (err) | 349 | if (err) |
@@ -351,6 +351,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
351 | 351 | ||
352 | pid = NETLINK_CREDS(skb)->pid; | 352 | pid = NETLINK_CREDS(skb)->pid; |
353 | uid = NETLINK_CREDS(skb)->uid; | 353 | uid = NETLINK_CREDS(skb)->uid; |
354 | loginuid = NETLINK_CB(skb).loginuid; | ||
354 | seq = nlh->nlmsg_seq; | 355 | seq = nlh->nlmsg_seq; |
355 | data = NLMSG_DATA(nlh); | 356 | data = NLMSG_DATA(nlh); |
356 | 357 | ||
@@ -371,34 +372,36 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
371 | return -EINVAL; | 372 | return -EINVAL; |
372 | status_get = (struct audit_status *)data; | 373 | status_get = (struct audit_status *)data; |
373 | if (status_get->mask & AUDIT_STATUS_ENABLED) { | 374 | if (status_get->mask & AUDIT_STATUS_ENABLED) { |
374 | err = audit_set_enabled(status_get->enabled); | 375 | err = audit_set_enabled(status_get->enabled, loginuid); |
375 | if (err < 0) return err; | 376 | if (err < 0) return err; |
376 | } | 377 | } |
377 | if (status_get->mask & AUDIT_STATUS_FAILURE) { | 378 | if (status_get->mask & AUDIT_STATUS_FAILURE) { |
378 | err = audit_set_failure(status_get->failure); | 379 | err = audit_set_failure(status_get->failure, loginuid); |
379 | if (err < 0) return err; | 380 | if (err < 0) return err; |
380 | } | 381 | } |
381 | if (status_get->mask & AUDIT_STATUS_PID) { | 382 | if (status_get->mask & AUDIT_STATUS_PID) { |
382 | int old = audit_pid; | 383 | int old = audit_pid; |
383 | audit_pid = status_get->pid; | 384 | audit_pid = status_get->pid; |
384 | audit_log(current->audit_context, | 385 | audit_log(NULL, "audit_pid=%d old=%d by auid %u", |
385 | "audit_pid=%d old=%d", audit_pid, old); | 386 | audit_pid, old, loginuid); |
386 | } | 387 | } |
387 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) | 388 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) |
388 | audit_set_rate_limit(status_get->rate_limit); | 389 | audit_set_rate_limit(status_get->rate_limit, loginuid); |
389 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) | 390 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) |
390 | audit_set_backlog_limit(status_get->backlog_limit); | 391 | audit_set_backlog_limit(status_get->backlog_limit, |
392 | loginuid); | ||
391 | break; | 393 | break; |
392 | case AUDIT_USER: | 394 | case AUDIT_USER: |
393 | ab = audit_log_start(NULL); | 395 | ab = audit_log_start(NULL); |
394 | if (!ab) | 396 | if (!ab) |
395 | break; /* audit_panic has been called */ | 397 | break; /* audit_panic has been called */ |
396 | audit_log_format(ab, | 398 | audit_log_format(ab, |
397 | "user pid=%d uid=%d length=%d msg='%.1024s'", | 399 | "user pid=%d uid=%d length=%d loginuid=%u" |
400 | " msg='%.1024s'", | ||
398 | pid, uid, | 401 | pid, uid, |
399 | (int)(nlh->nlmsg_len | 402 | (int)(nlh->nlmsg_len |
400 | - ((char *)data - (char *)nlh)), | 403 | - ((char *)data - (char *)nlh)), |
401 | (char *)data); | 404 | loginuid, (char *)data); |
402 | ab->type = AUDIT_USER; | 405 | ab->type = AUDIT_USER; |
403 | ab->pid = pid; | 406 | ab->pid = pid; |
404 | audit_log_end(ab); | 407 | audit_log_end(ab); |
@@ -411,7 +414,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
411 | case AUDIT_LIST: | 414 | case AUDIT_LIST: |
412 | #ifdef CONFIG_AUDITSYSCALL | 415 | #ifdef CONFIG_AUDITSYSCALL |
413 | err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, | 416 | err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, |
414 | uid, seq, data); | 417 | uid, seq, data, loginuid); |
415 | #else | 418 | #else |
416 | err = -EOPNOTSUPP; | 419 | err = -EOPNOTSUPP; |
417 | #endif | 420 | #endif |
@@ -427,7 +430,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
427 | /* Get message from skb (based on rtnetlink_rcv_skb). Each message is | 430 | /* Get message from skb (based on rtnetlink_rcv_skb). Each message is |
428 | * processed by audit_receive_msg. Malformed skbs with wrong length are | 431 | * processed by audit_receive_msg. Malformed skbs with wrong length are |
429 | * discarded silently. */ | 432 | * discarded silently. */ |
430 | static int audit_receive_skb(struct sk_buff *skb) | 433 | static void audit_receive_skb(struct sk_buff *skb) |
431 | { | 434 | { |
432 | int err; | 435 | int err; |
433 | struct nlmsghdr *nlh; | 436 | struct nlmsghdr *nlh; |
@@ -436,7 +439,7 @@ static int audit_receive_skb(struct sk_buff *skb) | |||
436 | while (skb->len >= NLMSG_SPACE(0)) { | 439 | while (skb->len >= NLMSG_SPACE(0)) { |
437 | nlh = (struct nlmsghdr *)skb->data; | 440 | nlh = (struct nlmsghdr *)skb->data; |
438 | if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) | 441 | if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) |
439 | return 0; | 442 | return; |
440 | rlen = NLMSG_ALIGN(nlh->nlmsg_len); | 443 | rlen = NLMSG_ALIGN(nlh->nlmsg_len); |
441 | if (rlen > skb->len) | 444 | if (rlen > skb->len) |
442 | rlen = skb->len; | 445 | rlen = skb->len; |
@@ -446,23 +449,20 @@ static int audit_receive_skb(struct sk_buff *skb) | |||
446 | netlink_ack(skb, nlh, 0); | 449 | netlink_ack(skb, nlh, 0); |
447 | skb_pull(skb, rlen); | 450 | skb_pull(skb, rlen); |
448 | } | 451 | } |
449 | return 0; | ||
450 | } | 452 | } |
451 | 453 | ||
452 | /* Receive messages from netlink socket. */ | 454 | /* Receive messages from netlink socket. */ |
453 | static void audit_receive(struct sock *sk, int length) | 455 | static void audit_receive(struct sock *sk, int length) |
454 | { | 456 | { |
455 | struct sk_buff *skb; | 457 | struct sk_buff *skb; |
458 | unsigned int qlen; | ||
456 | 459 | ||
457 | if (down_trylock(&audit_netlink_sem)) | 460 | down(&audit_netlink_sem); |
458 | return; | ||
459 | 461 | ||
460 | /* FIXME: this must not cause starvation */ | 462 | for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) { |
461 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { | 463 | skb = skb_dequeue(&sk->sk_receive_queue); |
462 | if (audit_receive_skb(skb) && skb->len) | 464 | audit_receive_skb(skb); |
463 | skb_queue_head(&sk->sk_receive_queue, skb); | 465 | kfree_skb(skb); |
464 | else | ||
465 | kfree_skb(skb); | ||
466 | } | 466 | } |
467 | up(&audit_netlink_sem); | 467 | up(&audit_netlink_sem); |
468 | } | 468 | } |
@@ -483,7 +483,7 @@ static void audit_log_move(struct audit_buffer *ab) | |||
483 | if (ab->len == 0) | 483 | if (ab->len == 0) |
484 | return; | 484 | return; |
485 | 485 | ||
486 | skb = skb_peek(&ab->sklist); | 486 | skb = skb_peek_tail(&ab->sklist); |
487 | if (!skb || skb_tailroom(skb) <= ab->len + extra) { | 487 | if (!skb || skb_tailroom(skb) <= ab->len + extra) { |
488 | skb = alloc_skb(2 * ab->len + extra, GFP_ATOMIC); | 488 | skb = alloc_skb(2 * ab->len + extra, GFP_ATOMIC); |
489 | if (!skb) { | 489 | if (!skb) { |
@@ -522,9 +522,9 @@ static inline int audit_log_drain(struct audit_buffer *ab) | |||
522 | retval = netlink_unicast(audit_sock, skb, audit_pid, | 522 | retval = netlink_unicast(audit_sock, skb, audit_pid, |
523 | MSG_DONTWAIT); | 523 | MSG_DONTWAIT); |
524 | } | 524 | } |
525 | if (retval == -EAGAIN && ab->count < 5) { | 525 | if (retval == -EAGAIN && |
526 | ++ab->count; | 526 | (atomic_read(&audit_backlog)) < audit_backlog_limit) { |
527 | skb_queue_tail(&ab->sklist, skb); | 527 | skb_queue_head(&ab->sklist, skb); |
528 | audit_log_end_irq(ab); | 528 | audit_log_end_irq(ab); |
529 | return 1; | 529 | return 1; |
530 | } | 530 | } |
@@ -540,8 +540,8 @@ static inline int audit_log_drain(struct audit_buffer *ab) | |||
540 | if (!audit_pid) { /* No daemon */ | 540 | if (!audit_pid) { /* No daemon */ |
541 | int offset = ab->nlh ? NLMSG_SPACE(0) : 0; | 541 | int offset = ab->nlh ? NLMSG_SPACE(0) : 0; |
542 | int len = skb->len - offset; | 542 | int len = skb->len - offset; |
543 | printk(KERN_ERR "%*.*s\n", | 543 | skb->data[offset + len] = '\0'; |
544 | len, len, skb->data + offset); | 544 | printk(KERN_ERR "%s\n", skb->data + offset); |
545 | } | 545 | } |
546 | kfree_skb(skb); | 546 | kfree_skb(skb); |
547 | ab->nlh = NULL; | 547 | ab->nlh = NULL; |
@@ -620,7 +620,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx) | |||
620 | struct audit_buffer *ab = NULL; | 620 | struct audit_buffer *ab = NULL; |
621 | unsigned long flags; | 621 | unsigned long flags; |
622 | struct timespec t; | 622 | struct timespec t; |
623 | int serial = 0; | 623 | unsigned int serial; |
624 | 624 | ||
625 | if (!audit_initialized) | 625 | if (!audit_initialized) |
626 | return NULL; | 626 | return NULL; |
@@ -662,15 +662,16 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx) | |||
662 | ab->total = 0; | 662 | ab->total = 0; |
663 | ab->type = AUDIT_KERNEL; | 663 | ab->type = AUDIT_KERNEL; |
664 | ab->pid = 0; | 664 | ab->pid = 0; |
665 | ab->count = 0; | ||
666 | 665 | ||
667 | #ifdef CONFIG_AUDITSYSCALL | 666 | #ifdef CONFIG_AUDITSYSCALL |
668 | if (ab->ctx) | 667 | if (ab->ctx) |
669 | audit_get_stamp(ab->ctx, &t, &serial); | 668 | audit_get_stamp(ab->ctx, &t, &serial); |
670 | else | 669 | else |
671 | #endif | 670 | #endif |
671 | { | ||
672 | t = CURRENT_TIME; | 672 | t = CURRENT_TIME; |
673 | 673 | serial = 0; | |
674 | } | ||
674 | audit_log_format(ab, "audit(%lu.%03lu:%u): ", | 675 | audit_log_format(ab, "audit(%lu.%03lu:%u): ", |
675 | t.tv_sec, t.tv_nsec/1000000, serial); | 676 | t.tv_sec, t.tv_nsec/1000000, serial); |
676 | return ab; | 677 | return ab; |
@@ -720,6 +721,29 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...) | |||
720 | va_end(args); | 721 | va_end(args); |
721 | } | 722 | } |
722 | 723 | ||
724 | void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, size_t len) | ||
725 | { | ||
726 | int i; | ||
727 | |||
728 | for (i=0; i<len; i++) | ||
729 | audit_log_format(ab, "%02x", buf[i]); | ||
730 | } | ||
731 | |||
732 | void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) | ||
733 | { | ||
734 | const unsigned char *p = string; | ||
735 | |||
736 | while (*p) { | ||
737 | if (*p == '"' || *p == ' ' || *p < 0x20 || *p > 0x7f) { | ||
738 | audit_log_hex(ab, string, strlen(string)); | ||
739 | return; | ||
740 | } | ||
741 | p++; | ||
742 | } | ||
743 | audit_log_format(ab, "\"%s\"", string); | ||
744 | } | ||
745 | |||
746 | |||
723 | /* This is a helper-function to print the d_path without using a static | 747 | /* This is a helper-function to print the d_path without using a static |
724 | * buffer or allocating another buffer in addition to the one in | 748 | * buffer or allocating another buffer in addition to the one in |
725 | * audit_buffer. */ | 749 | * audit_buffer. */ |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 6f1931381bc9..37b3ac94bc47 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* auditsc.c -- System-call auditing support -*- linux-c -*- | 1 | /* auditsc.c -- System-call auditing support |
2 | * Handles all system-call specific auditing features. | 2 | * Handles all system-call specific auditing features. |
3 | * | 3 | * |
4 | * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. | 4 | * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. |
@@ -123,7 +123,7 @@ struct audit_context { | |||
123 | int major; /* syscall number */ | 123 | int major; /* syscall number */ |
124 | unsigned long argv[4]; /* syscall arguments */ | 124 | unsigned long argv[4]; /* syscall arguments */ |
125 | int return_valid; /* return code is valid */ | 125 | int return_valid; /* return code is valid */ |
126 | int return_code;/* syscall return code */ | 126 | long return_code;/* syscall return code */ |
127 | int auditable; /* 1 if record should be written */ | 127 | int auditable; /* 1 if record should be written */ |
128 | int name_count; | 128 | int name_count; |
129 | struct audit_names names[AUDIT_NAMES]; | 129 | struct audit_names names[AUDIT_NAMES]; |
@@ -135,6 +135,7 @@ struct audit_context { | |||
135 | uid_t uid, euid, suid, fsuid; | 135 | uid_t uid, euid, suid, fsuid; |
136 | gid_t gid, egid, sgid, fsgid; | 136 | gid_t gid, egid, sgid, fsgid; |
137 | unsigned long personality; | 137 | unsigned long personality; |
138 | int arch; | ||
138 | 139 | ||
139 | #if AUDIT_DEBUG | 140 | #if AUDIT_DEBUG |
140 | int put_count; | 141 | int put_count; |
@@ -250,7 +251,8 @@ static int audit_copy_rule(struct audit_rule *d, struct audit_rule *s) | |||
250 | return 0; | 251 | return 0; |
251 | } | 252 | } |
252 | 253 | ||
253 | int audit_receive_filter(int type, int pid, int uid, int seq, void *data) | 254 | int audit_receive_filter(int type, int pid, int uid, int seq, void *data, |
255 | uid_t loginuid) | ||
254 | { | 256 | { |
255 | u32 flags; | 257 | u32 flags; |
256 | struct audit_entry *entry; | 258 | struct audit_entry *entry; |
@@ -285,6 +287,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data) | |||
285 | err = audit_add_rule(entry, &audit_entlist); | 287 | err = audit_add_rule(entry, &audit_entlist); |
286 | if (!err && (flags & AUDIT_AT_EXIT)) | 288 | if (!err && (flags & AUDIT_AT_EXIT)) |
287 | err = audit_add_rule(entry, &audit_extlist); | 289 | err = audit_add_rule(entry, &audit_extlist); |
290 | audit_log(NULL, "auid %u added an audit rule\n", loginuid); | ||
288 | break; | 291 | break; |
289 | case AUDIT_DEL: | 292 | case AUDIT_DEL: |
290 | flags =((struct audit_rule *)data)->flags; | 293 | flags =((struct audit_rule *)data)->flags; |
@@ -294,6 +297,7 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data) | |||
294 | err = audit_del_rule(data, &audit_entlist); | 297 | err = audit_del_rule(data, &audit_entlist); |
295 | if (!err && (flags & AUDIT_AT_EXIT)) | 298 | if (!err && (flags & AUDIT_AT_EXIT)) |
296 | err = audit_del_rule(data, &audit_extlist); | 299 | err = audit_del_rule(data, &audit_extlist); |
300 | audit_log(NULL, "auid %u removed an audit rule\n", loginuid); | ||
297 | break; | 301 | break; |
298 | default: | 302 | default: |
299 | return -EINVAL; | 303 | return -EINVAL; |
@@ -348,6 +352,10 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
348 | case AUDIT_PERS: | 352 | case AUDIT_PERS: |
349 | result = (tsk->personality == value); | 353 | result = (tsk->personality == value); |
350 | break; | 354 | break; |
355 | case AUDIT_ARCH: | ||
356 | if (ctx) | ||
357 | result = (ctx->arch == value); | ||
358 | break; | ||
351 | 359 | ||
352 | case AUDIT_EXIT: | 360 | case AUDIT_EXIT: |
353 | if (ctx && ctx->return_valid) | 361 | if (ctx && ctx->return_valid) |
@@ -355,7 +363,7 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
355 | break; | 363 | break; |
356 | case AUDIT_SUCCESS: | 364 | case AUDIT_SUCCESS: |
357 | if (ctx && ctx->return_valid) | 365 | if (ctx && ctx->return_valid) |
358 | result = (ctx->return_code >= 0); | 366 | result = (ctx->return_valid == AUDITSC_SUCCESS); |
359 | break; | 367 | break; |
360 | case AUDIT_DEVMAJOR: | 368 | case AUDIT_DEVMAJOR: |
361 | if (ctx) { | 369 | if (ctx) { |
@@ -648,8 +656,11 @@ static void audit_log_exit(struct audit_context *context) | |||
648 | audit_log_format(ab, "syscall=%d", context->major); | 656 | audit_log_format(ab, "syscall=%d", context->major); |
649 | if (context->personality != PER_LINUX) | 657 | if (context->personality != PER_LINUX) |
650 | audit_log_format(ab, " per=%lx", context->personality); | 658 | audit_log_format(ab, " per=%lx", context->personality); |
659 | audit_log_format(ab, " arch=%x", context->arch); | ||
651 | if (context->return_valid) | 660 | if (context->return_valid) |
652 | audit_log_format(ab, " exit=%d", context->return_code); | 661 | audit_log_format(ab, " success=%s exit=%ld", |
662 | (context->return_valid==AUDITSC_SUCCESS)?"yes":"no", | ||
663 | context->return_code); | ||
653 | audit_log_format(ab, | 664 | audit_log_format(ab, |
654 | " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" | 665 | " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" |
655 | " pid=%d loginuid=%d uid=%d gid=%d" | 666 | " pid=%d loginuid=%d uid=%d gid=%d" |
@@ -696,9 +707,10 @@ static void audit_log_exit(struct audit_context *context) | |||
696 | if (!ab) | 707 | if (!ab) |
697 | continue; /* audit_panic has been called */ | 708 | continue; /* audit_panic has been called */ |
698 | audit_log_format(ab, "item=%d", i); | 709 | audit_log_format(ab, "item=%d", i); |
699 | if (context->names[i].name) | 710 | if (context->names[i].name) { |
700 | audit_log_format(ab, " name=%s", | 711 | audit_log_format(ab, " name="); |
701 | context->names[i].name); | 712 | audit_log_untrustedstring(ab, context->names[i].name); |
713 | } | ||
702 | if (context->names[i].ino != (unsigned long)-1) | 714 | if (context->names[i].ino != (unsigned long)-1) |
703 | audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o" | 715 | audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o" |
704 | " uid=%d gid=%d rdev=%02x:%02x", | 716 | " uid=%d gid=%d rdev=%02x:%02x", |
@@ -772,7 +784,7 @@ static inline unsigned int audit_serial(void) | |||
772 | * then the record will be written at syscall exit time (otherwise, it | 784 | * then the record will be written at syscall exit time (otherwise, it |
773 | * will only be written if another part of the kernel requests that it | 785 | * will only be written if another part of the kernel requests that it |
774 | * be written). */ | 786 | * be written). */ |
775 | void audit_syscall_entry(struct task_struct *tsk, int major, | 787 | void audit_syscall_entry(struct task_struct *tsk, int arch, int major, |
776 | unsigned long a1, unsigned long a2, | 788 | unsigned long a1, unsigned long a2, |
777 | unsigned long a3, unsigned long a4) | 789 | unsigned long a3, unsigned long a4) |
778 | { | 790 | { |
@@ -826,6 +838,7 @@ void audit_syscall_entry(struct task_struct *tsk, int major, | |||
826 | if (!audit_enabled) | 838 | if (!audit_enabled) |
827 | return; | 839 | return; |
828 | 840 | ||
841 | context->arch = arch; | ||
829 | context->major = major; | 842 | context->major = major; |
830 | context->argv[0] = a1; | 843 | context->argv[0] = a1; |
831 | context->argv[1] = a2; | 844 | context->argv[1] = a2; |
@@ -849,13 +862,13 @@ void audit_syscall_entry(struct task_struct *tsk, int major, | |||
849 | * filtering, or because some other part of the kernel write an audit | 862 | * filtering, or because some other part of the kernel write an audit |
850 | * message), then write out the syscall information. In call cases, | 863 | * message), then write out the syscall information. In call cases, |
851 | * free the names stored from getname(). */ | 864 | * free the names stored from getname(). */ |
852 | void audit_syscall_exit(struct task_struct *tsk, int return_code) | 865 | void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code) |
853 | { | 866 | { |
854 | struct audit_context *context; | 867 | struct audit_context *context; |
855 | 868 | ||
856 | get_task_struct(tsk); | 869 | get_task_struct(tsk); |
857 | task_lock(tsk); | 870 | task_lock(tsk); |
858 | context = audit_get_context(tsk, 1, return_code); | 871 | context = audit_get_context(tsk, valid, return_code); |
859 | task_unlock(tsk); | 872 | task_unlock(tsk); |
860 | 873 | ||
861 | /* Not having a context here is ok, since the parent may have | 874 | /* Not having a context here is ok, since the parent may have |
@@ -868,6 +881,7 @@ void audit_syscall_exit(struct task_struct *tsk, int return_code) | |||
868 | 881 | ||
869 | context->in_syscall = 0; | 882 | context->in_syscall = 0; |
870 | context->auditable = 0; | 883 | context->auditable = 0; |
884 | |||
871 | if (context->previous) { | 885 | if (context->previous) { |
872 | struct audit_context *new_context = context->previous; | 886 | struct audit_context *new_context = context->previous; |
873 | context->previous = NULL; | 887 | context->previous = NULL; |
@@ -981,7 +995,7 @@ void audit_inode(const char *name, const struct inode *inode) | |||
981 | } | 995 | } |
982 | 996 | ||
983 | void audit_get_stamp(struct audit_context *ctx, | 997 | void audit_get_stamp(struct audit_context *ctx, |
984 | struct timespec *t, int *serial) | 998 | struct timespec *t, unsigned int *serial) |
985 | { | 999 | { |
986 | if (ctx) { | 1000 | if (ctx) { |
987 | t->tv_sec = ctx->ctime.tv_sec; | 1001 | t->tv_sec = ctx->ctime.tv_sec; |
@@ -996,20 +1010,21 @@ void audit_get_stamp(struct audit_context *ctx, | |||
996 | 1010 | ||
997 | extern int audit_set_type(struct audit_buffer *ab, int type); | 1011 | extern int audit_set_type(struct audit_buffer *ab, int type); |
998 | 1012 | ||
999 | int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid) | 1013 | int audit_set_loginuid(struct task_struct *task, uid_t loginuid) |
1000 | { | 1014 | { |
1001 | if (ctx) { | 1015 | if (task->audit_context) { |
1002 | struct audit_buffer *ab; | 1016 | struct audit_buffer *ab; |
1003 | 1017 | ||
1004 | ab = audit_log_start(NULL); | 1018 | ab = audit_log_start(NULL); |
1005 | if (ab) { | 1019 | if (ab) { |
1006 | audit_log_format(ab, "login pid=%d uid=%u " | 1020 | audit_log_format(ab, "login pid=%d uid=%u " |
1007 | "old loginuid=%u new loginuid=%u", | 1021 | "old loginuid=%u new loginuid=%u", |
1008 | ctx->pid, ctx->uid, ctx->loginuid, loginuid); | 1022 | task->pid, task->uid, |
1023 | task->audit_context->loginuid, loginuid); | ||
1009 | audit_set_type(ab, AUDIT_LOGIN); | 1024 | audit_set_type(ab, AUDIT_LOGIN); |
1010 | audit_log_end(ab); | 1025 | audit_log_end(ab); |
1011 | } | 1026 | } |
1012 | ctx->loginuid = loginuid; | 1027 | task->audit_context->loginuid = loginuid; |
1013 | } | 1028 | } |
1014 | return 0; | 1029 | return 0; |
1015 | } | 1030 | } |
diff --git a/kernel/exit.c b/kernel/exit.c index 39d35935b371..edaa50b5bbfa 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/mempolicy.h> | 27 | #include <linux/mempolicy.h> |
28 | #include <linux/cpuset.h> | 28 | #include <linux/cpuset.h> |
29 | #include <linux/syscalls.h> | 29 | #include <linux/syscalls.h> |
30 | #include <linux/signal.h> | ||
30 | 31 | ||
31 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
32 | #include <asm/unistd.h> | 33 | #include <asm/unistd.h> |
@@ -38,6 +39,8 @@ extern struct task_struct *child_reaper; | |||
38 | 39 | ||
39 | int getrusage(struct task_struct *, int, struct rusage __user *); | 40 | int getrusage(struct task_struct *, int, struct rusage __user *); |
40 | 41 | ||
42 | static void exit_mm(struct task_struct * tsk); | ||
43 | |||
41 | static void __unhash_process(struct task_struct *p) | 44 | static void __unhash_process(struct task_struct *p) |
42 | { | 45 | { |
43 | nr_threads--; | 46 | nr_threads--; |
@@ -209,7 +212,7 @@ static inline int has_stopped_jobs(int pgrp) | |||
209 | } | 212 | } |
210 | 213 | ||
211 | /** | 214 | /** |
212 | * reparent_to_init() - Reparent the calling kernel thread to the init task. | 215 | * reparent_to_init - Reparent the calling kernel thread to the init task. |
213 | * | 216 | * |
214 | * If a kernel thread is launched as a result of a system call, or if | 217 | * If a kernel thread is launched as a result of a system call, or if |
215 | * it ever exits, it should generally reparent itself to init so that | 218 | * it ever exits, it should generally reparent itself to init so that |
@@ -277,7 +280,7 @@ void set_special_pids(pid_t session, pid_t pgrp) | |||
277 | */ | 280 | */ |
278 | int allow_signal(int sig) | 281 | int allow_signal(int sig) |
279 | { | 282 | { |
280 | if (sig < 1 || sig > _NSIG) | 283 | if (!valid_signal(sig) || sig < 1) |
281 | return -EINVAL; | 284 | return -EINVAL; |
282 | 285 | ||
283 | spin_lock_irq(¤t->sighand->siglock); | 286 | spin_lock_irq(¤t->sighand->siglock); |
@@ -298,7 +301,7 @@ EXPORT_SYMBOL(allow_signal); | |||
298 | 301 | ||
299 | int disallow_signal(int sig) | 302 | int disallow_signal(int sig) |
300 | { | 303 | { |
301 | if (sig < 1 || sig > _NSIG) | 304 | if (!valid_signal(sig) || sig < 1) |
302 | return -EINVAL; | 305 | return -EINVAL; |
303 | 306 | ||
304 | spin_lock_irq(¤t->sighand->siglock); | 307 | spin_lock_irq(¤t->sighand->siglock); |
@@ -473,7 +476,7 @@ EXPORT_SYMBOL_GPL(exit_fs); | |||
473 | * Turn us into a lazy TLB process if we | 476 | * Turn us into a lazy TLB process if we |
474 | * aren't already.. | 477 | * aren't already.. |
475 | */ | 478 | */ |
476 | void exit_mm(struct task_struct * tsk) | 479 | static void exit_mm(struct task_struct * tsk) |
477 | { | 480 | { |
478 | struct mm_struct *mm = tsk->mm; | 481 | struct mm_struct *mm = tsk->mm; |
479 | 482 | ||
@@ -517,8 +520,6 @@ static inline void choose_new_parent(task_t *p, task_t *reaper, task_t *child_re | |||
517 | */ | 520 | */ |
518 | BUG_ON(p == reaper || reaper->exit_state >= EXIT_ZOMBIE); | 521 | BUG_ON(p == reaper || reaper->exit_state >= EXIT_ZOMBIE); |
519 | p->real_parent = reaper; | 522 | p->real_parent = reaper; |
520 | if (p->parent == p->real_parent) | ||
521 | BUG(); | ||
522 | } | 523 | } |
523 | 524 | ||
524 | static inline void reparent_thread(task_t *p, task_t *father, int traced) | 525 | static inline void reparent_thread(task_t *p, task_t *father, int traced) |
@@ -845,6 +846,8 @@ fastcall NORET_TYPE void do_exit(long code) | |||
845 | for (;;) ; | 846 | for (;;) ; |
846 | } | 847 | } |
847 | 848 | ||
849 | EXPORT_SYMBOL_GPL(do_exit); | ||
850 | |||
848 | NORET_TYPE void complete_and_exit(struct completion *comp, long code) | 851 | NORET_TYPE void complete_and_exit(struct completion *comp, long code) |
849 | { | 852 | { |
850 | if (comp) | 853 | if (comp) |
diff --git a/kernel/futex.c b/kernel/futex.c index 7b54a672d0ad..c7130f86106c 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/mount.h> | 39 | #include <linux/mount.h> |
40 | #include <linux/pagemap.h> | 40 | #include <linux/pagemap.h> |
41 | #include <linux/syscalls.h> | 41 | #include <linux/syscalls.h> |
42 | #include <linux/signal.h> | ||
42 | 43 | ||
43 | #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8) | 44 | #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8) |
44 | 45 | ||
@@ -654,7 +655,7 @@ static int futex_fd(unsigned long uaddr, int signal) | |||
654 | int ret, err; | 655 | int ret, err; |
655 | 656 | ||
656 | ret = -EINVAL; | 657 | ret = -EINVAL; |
657 | if (signal < 0 || signal > _NSIG) | 658 | if (!valid_signal(signal)) |
658 | goto out; | 659 | goto out; |
659 | 660 | ||
660 | ret = get_unused_fd(); | 661 | ret = get_unused_fd(); |
diff --git a/kernel/itimer.c b/kernel/itimer.c index e9a40e947e07..1dc988e0d2c7 100644 --- a/kernel/itimer.c +++ b/kernel/itimer.c | |||
@@ -123,7 +123,11 @@ static inline void it_real_arm(struct task_struct *p, unsigned long interval) | |||
123 | return; | 123 | return; |
124 | if (interval > (unsigned long) LONG_MAX) | 124 | if (interval > (unsigned long) LONG_MAX) |
125 | interval = LONG_MAX; | 125 | interval = LONG_MAX; |
126 | p->signal->real_timer.expires = jiffies + interval; | 126 | /* the "+ 1" below makes sure that the timer doesn't go off before |
127 | * the interval requested. This could happen if | ||
128 | * time requested % (usecs per jiffy) is more than the usecs left | ||
129 | * in the current jiffy */ | ||
130 | p->signal->real_timer.expires = jiffies + interval + 1; | ||
127 | add_timer(&p->signal->real_timer); | 131 | add_timer(&p->signal->real_timer); |
128 | } | 132 | } |
129 | 133 | ||
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 1627f8d6e0cd..13bcec151b57 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c | |||
@@ -46,6 +46,14 @@ static inline int is_kernel_inittext(unsigned long addr) | |||
46 | return 0; | 46 | return 0; |
47 | } | 47 | } |
48 | 48 | ||
49 | static inline int is_kernel_extratext(unsigned long addr) | ||
50 | { | ||
51 | if (addr >= (unsigned long)_sextratext | ||
52 | && addr <= (unsigned long)_eextratext) | ||
53 | return 1; | ||
54 | return 0; | ||
55 | } | ||
56 | |||
49 | static inline int is_kernel_text(unsigned long addr) | 57 | static inline int is_kernel_text(unsigned long addr) |
50 | { | 58 | { |
51 | if (addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) | 59 | if (addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) |
@@ -169,8 +177,9 @@ const char *kallsyms_lookup(unsigned long addr, | |||
169 | namebuf[0] = 0; | 177 | namebuf[0] = 0; |
170 | 178 | ||
171 | if ((all_var && is_kernel(addr)) || | 179 | if ((all_var && is_kernel(addr)) || |
172 | (!all_var && (is_kernel_text(addr) || is_kernel_inittext(addr)))) { | 180 | (!all_var && (is_kernel_text(addr) || is_kernel_inittext(addr) || |
173 | unsigned long symbol_end=0; | 181 | is_kernel_extratext(addr)))) { |
182 | unsigned long symbol_end = 0; | ||
174 | 183 | ||
175 | /* do a binary search on the sorted kallsyms_addresses array */ | 184 | /* do a binary search on the sorted kallsyms_addresses array */ |
176 | low = 0; | 185 | low = 0; |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 1d5dd1337bd1..037142b72a49 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -44,6 +44,7 @@ static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; | |||
44 | 44 | ||
45 | unsigned int kprobe_cpu = NR_CPUS; | 45 | unsigned int kprobe_cpu = NR_CPUS; |
46 | static DEFINE_SPINLOCK(kprobe_lock); | 46 | static DEFINE_SPINLOCK(kprobe_lock); |
47 | static struct kprobe *curr_kprobe; | ||
47 | 48 | ||
48 | /* Locks kprobe: irqs must be disabled */ | 49 | /* Locks kprobe: irqs must be disabled */ |
49 | void lock_kprobes(void) | 50 | void lock_kprobes(void) |
@@ -73,22 +74,139 @@ struct kprobe *get_kprobe(void *addr) | |||
73 | return NULL; | 74 | return NULL; |
74 | } | 75 | } |
75 | 76 | ||
77 | /* | ||
78 | * Aggregate handlers for multiple kprobes support - these handlers | ||
79 | * take care of invoking the individual kprobe handlers on p->list | ||
80 | */ | ||
81 | int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) | ||
82 | { | ||
83 | struct kprobe *kp; | ||
84 | |||
85 | list_for_each_entry(kp, &p->list, list) { | ||
86 | if (kp->pre_handler) { | ||
87 | curr_kprobe = kp; | ||
88 | kp->pre_handler(kp, regs); | ||
89 | curr_kprobe = NULL; | ||
90 | } | ||
91 | } | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | void aggr_post_handler(struct kprobe *p, struct pt_regs *regs, | ||
96 | unsigned long flags) | ||
97 | { | ||
98 | struct kprobe *kp; | ||
99 | |||
100 | list_for_each_entry(kp, &p->list, list) { | ||
101 | if (kp->post_handler) { | ||
102 | curr_kprobe = kp; | ||
103 | kp->post_handler(kp, regs, flags); | ||
104 | curr_kprobe = NULL; | ||
105 | } | ||
106 | } | ||
107 | return; | ||
108 | } | ||
109 | |||
110 | int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr) | ||
111 | { | ||
112 | /* | ||
113 | * if we faulted "during" the execution of a user specified | ||
114 | * probe handler, invoke just that probe's fault handler | ||
115 | */ | ||
116 | if (curr_kprobe && curr_kprobe->fault_handler) { | ||
117 | if (curr_kprobe->fault_handler(curr_kprobe, regs, trapnr)) | ||
118 | return 1; | ||
119 | } | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Fill in the required fields of the "manager kprobe". Replace the | ||
125 | * earlier kprobe in the hlist with the manager kprobe | ||
126 | */ | ||
127 | static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p) | ||
128 | { | ||
129 | ap->addr = p->addr; | ||
130 | ap->opcode = p->opcode; | ||
131 | memcpy(&ap->ainsn, &p->ainsn, sizeof(struct arch_specific_insn)); | ||
132 | |||
133 | ap->pre_handler = aggr_pre_handler; | ||
134 | ap->post_handler = aggr_post_handler; | ||
135 | ap->fault_handler = aggr_fault_handler; | ||
136 | |||
137 | INIT_LIST_HEAD(&ap->list); | ||
138 | list_add(&p->list, &ap->list); | ||
139 | |||
140 | INIT_HLIST_NODE(&ap->hlist); | ||
141 | hlist_del(&p->hlist); | ||
142 | hlist_add_head(&ap->hlist, | ||
143 | &kprobe_table[hash_ptr(ap->addr, KPROBE_HASH_BITS)]); | ||
144 | } | ||
145 | |||
146 | /* | ||
147 | * This is the second or subsequent kprobe at the address - handle | ||
148 | * the intricacies | ||
149 | * TODO: Move kcalloc outside the spinlock | ||
150 | */ | ||
151 | static int register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p) | ||
152 | { | ||
153 | int ret = 0; | ||
154 | struct kprobe *ap; | ||
155 | |||
156 | if (old_p->break_handler || p->break_handler) { | ||
157 | ret = -EEXIST; /* kprobe and jprobe can't (yet) coexist */ | ||
158 | } else if (old_p->pre_handler == aggr_pre_handler) { | ||
159 | list_add(&p->list, &old_p->list); | ||
160 | } else { | ||
161 | ap = kcalloc(1, sizeof(struct kprobe), GFP_ATOMIC); | ||
162 | if (!ap) | ||
163 | return -ENOMEM; | ||
164 | add_aggr_kprobe(ap, old_p); | ||
165 | list_add(&p->list, &ap->list); | ||
166 | } | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | /* kprobe removal house-keeping routines */ | ||
171 | static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags) | ||
172 | { | ||
173 | *p->addr = p->opcode; | ||
174 | hlist_del(&p->hlist); | ||
175 | flush_icache_range((unsigned long) p->addr, | ||
176 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | ||
177 | spin_unlock_irqrestore(&kprobe_lock, flags); | ||
178 | arch_remove_kprobe(p); | ||
179 | } | ||
180 | |||
181 | static inline void cleanup_aggr_kprobe(struct kprobe *old_p, | ||
182 | struct kprobe *p, unsigned long flags) | ||
183 | { | ||
184 | list_del(&p->list); | ||
185 | if (list_empty(&old_p->list)) { | ||
186 | cleanup_kprobe(old_p, flags); | ||
187 | kfree(old_p); | ||
188 | } else | ||
189 | spin_unlock_irqrestore(&kprobe_lock, flags); | ||
190 | } | ||
191 | |||
76 | int register_kprobe(struct kprobe *p) | 192 | int register_kprobe(struct kprobe *p) |
77 | { | 193 | { |
78 | int ret = 0; | 194 | int ret = 0; |
79 | unsigned long flags = 0; | 195 | unsigned long flags = 0; |
196 | struct kprobe *old_p; | ||
80 | 197 | ||
81 | if ((ret = arch_prepare_kprobe(p)) != 0) { | 198 | if ((ret = arch_prepare_kprobe(p)) != 0) { |
82 | goto rm_kprobe; | 199 | goto rm_kprobe; |
83 | } | 200 | } |
84 | spin_lock_irqsave(&kprobe_lock, flags); | 201 | spin_lock_irqsave(&kprobe_lock, flags); |
85 | INIT_HLIST_NODE(&p->hlist); | 202 | old_p = get_kprobe(p->addr); |
86 | if (get_kprobe(p->addr)) { | 203 | if (old_p) { |
87 | ret = -EEXIST; | 204 | ret = register_aggr_kprobe(old_p, p); |
88 | goto out; | 205 | goto out; |
89 | } | 206 | } |
90 | arch_copy_kprobe(p); | ||
91 | 207 | ||
208 | arch_copy_kprobe(p); | ||
209 | INIT_HLIST_NODE(&p->hlist); | ||
92 | hlist_add_head(&p->hlist, | 210 | hlist_add_head(&p->hlist, |
93 | &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); | 211 | &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); |
94 | 212 | ||
@@ -107,13 +225,17 @@ rm_kprobe: | |||
107 | void unregister_kprobe(struct kprobe *p) | 225 | void unregister_kprobe(struct kprobe *p) |
108 | { | 226 | { |
109 | unsigned long flags; | 227 | unsigned long flags; |
110 | arch_remove_kprobe(p); | 228 | struct kprobe *old_p; |
229 | |||
111 | spin_lock_irqsave(&kprobe_lock, flags); | 230 | spin_lock_irqsave(&kprobe_lock, flags); |
112 | *p->addr = p->opcode; | 231 | old_p = get_kprobe(p->addr); |
113 | hlist_del(&p->hlist); | 232 | if (old_p) { |
114 | flush_icache_range((unsigned long) p->addr, | 233 | if (old_p->pre_handler == aggr_pre_handler) |
115 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | 234 | cleanup_aggr_kprobe(old_p, p, flags); |
116 | spin_unlock_irqrestore(&kprobe_lock, flags); | 235 | else |
236 | cleanup_kprobe(p, flags); | ||
237 | } else | ||
238 | spin_unlock_irqrestore(&kprobe_lock, flags); | ||
117 | } | 239 | } |
118 | 240 | ||
119 | static struct notifier_block kprobe_exceptions_nb = { | 241 | static struct notifier_block kprobe_exceptions_nb = { |
diff --git a/kernel/kthread.c b/kernel/kthread.c index e377e2244103..f50f174e92da 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c | |||
@@ -174,7 +174,7 @@ int kthread_stop(struct task_struct *k) | |||
174 | 174 | ||
175 | /* Must init completion *before* thread sees kthread_stop_info.k */ | 175 | /* Must init completion *before* thread sees kthread_stop_info.k */ |
176 | init_completion(&kthread_stop_info.done); | 176 | init_completion(&kthread_stop_info.done); |
177 | wmb(); | 177 | smp_wmb(); |
178 | 178 | ||
179 | /* Now set kthread_should_stop() to true, and wake it up. */ | 179 | /* Now set kthread_should_stop() to true, and wake it up. */ |
180 | kthread_stop_info.k = k; | 180 | kthread_stop_info.k = k; |
diff --git a/kernel/module.c b/kernel/module.c index 2dbfa0773faf..5734ab09d3f9 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -1801,7 +1801,7 @@ sys_init_module(void __user *umod, | |||
1801 | /* Init routine failed: abort. Try to protect us from | 1801 | /* Init routine failed: abort. Try to protect us from |
1802 | buggy refcounters. */ | 1802 | buggy refcounters. */ |
1803 | mod->state = MODULE_STATE_GOING; | 1803 | mod->state = MODULE_STATE_GOING; |
1804 | synchronize_kernel(); | 1804 | synchronize_sched(); |
1805 | if (mod->unsafe) | 1805 | if (mod->unsafe) |
1806 | printk(KERN_ERR "%s: module is now stuck!\n", | 1806 | printk(KERN_ERR "%s: module is now stuck!\n", |
1807 | mod->name); | 1807 | mod->name); |
diff --git a/kernel/panic.c b/kernel/panic.c index 0fa3f3a66fb6..081f7465fc8d 100644 --- a/kernel/panic.c +++ b/kernel/panic.c | |||
@@ -102,9 +102,9 @@ NORET_TYPE void panic(const char * fmt, ...) | |||
102 | #ifdef __sparc__ | 102 | #ifdef __sparc__ |
103 | { | 103 | { |
104 | extern int stop_a_enabled; | 104 | extern int stop_a_enabled; |
105 | /* Make sure the user can actually press L1-A */ | 105 | /* Make sure the user can actually press Stop-A (L1-A) */ |
106 | stop_a_enabled = 1; | 106 | stop_a_enabled = 1; |
107 | printk(KERN_EMERG "Press L1-A to return to the boot prom\n"); | 107 | printk(KERN_EMERG "Press Stop-A (L1-A) to return to the boot prom\n"); |
108 | } | 108 | } |
109 | #endif | 109 | #endif |
110 | #if defined(CONFIG_ARCH_S390) | 110 | #if defined(CONFIG_ARCH_S390) |
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index ae5bebc3b18f..90b3b68dee3f 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c | |||
@@ -1099,7 +1099,7 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist) | |||
1099 | return pblist; | 1099 | return pblist; |
1100 | } | 1100 | } |
1101 | 1101 | ||
1102 | /** | 1102 | /* |
1103 | * Using bio to read from swap. | 1103 | * Using bio to read from swap. |
1104 | * This code requires a bit more work than just using buffer heads | 1104 | * This code requires a bit more work than just using buffer heads |
1105 | * but, it is the recommended way for 2.5/2.6. | 1105 | * but, it is the recommended way for 2.5/2.6. |
diff --git a/kernel/printk.c b/kernel/printk.c index 1498689548d1..290a07ce2c8a 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -85,10 +85,6 @@ static int console_locked; | |||
85 | */ | 85 | */ |
86 | static DEFINE_SPINLOCK(logbuf_lock); | 86 | static DEFINE_SPINLOCK(logbuf_lock); |
87 | 87 | ||
88 | static char __log_buf[__LOG_BUF_LEN]; | ||
89 | static char *log_buf = __log_buf; | ||
90 | static int log_buf_len = __LOG_BUF_LEN; | ||
91 | |||
92 | #define LOG_BUF_MASK (log_buf_len-1) | 88 | #define LOG_BUF_MASK (log_buf_len-1) |
93 | #define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK]) | 89 | #define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK]) |
94 | 90 | ||
@@ -99,7 +95,6 @@ static int log_buf_len = __LOG_BUF_LEN; | |||
99 | static unsigned long log_start; /* Index into log_buf: next char to be read by syslog() */ | 95 | static unsigned long log_start; /* Index into log_buf: next char to be read by syslog() */ |
100 | static unsigned long con_start; /* Index into log_buf: next char to be sent to consoles */ | 96 | static unsigned long con_start; /* Index into log_buf: next char to be sent to consoles */ |
101 | static unsigned long log_end; /* Index into log_buf: most-recently-written-char + 1 */ | 97 | static unsigned long log_end; /* Index into log_buf: most-recently-written-char + 1 */ |
102 | static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */ | ||
103 | 98 | ||
104 | /* | 99 | /* |
105 | * Array of consoles built from command line options (console=) | 100 | * Array of consoles built from command line options (console=) |
@@ -120,6 +115,13 @@ static int preferred_console = -1; | |||
120 | /* Flag: console code may call schedule() */ | 115 | /* Flag: console code may call schedule() */ |
121 | static int console_may_schedule; | 116 | static int console_may_schedule; |
122 | 117 | ||
118 | #ifdef CONFIG_PRINTK | ||
119 | |||
120 | static char __log_buf[__LOG_BUF_LEN]; | ||
121 | static char *log_buf = __log_buf; | ||
122 | static int log_buf_len = __LOG_BUF_LEN; | ||
123 | static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */ | ||
124 | |||
123 | /* | 125 | /* |
124 | * Setup a list of consoles. Called from init/main.c | 126 | * Setup a list of consoles. Called from init/main.c |
125 | */ | 127 | */ |
@@ -535,6 +537,7 @@ __setup("time", printk_time_setup); | |||
535 | * then changes console_loglevel may break. This is because console_loglevel | 537 | * then changes console_loglevel may break. This is because console_loglevel |
536 | * is inspected when the actual printing occurs. | 538 | * is inspected when the actual printing occurs. |
537 | */ | 539 | */ |
540 | |||
538 | asmlinkage int printk(const char *fmt, ...) | 541 | asmlinkage int printk(const char *fmt, ...) |
539 | { | 542 | { |
540 | va_list args; | 543 | va_list args; |
@@ -655,6 +658,18 @@ out: | |||
655 | EXPORT_SYMBOL(printk); | 658 | EXPORT_SYMBOL(printk); |
656 | EXPORT_SYMBOL(vprintk); | 659 | EXPORT_SYMBOL(vprintk); |
657 | 660 | ||
661 | #else | ||
662 | |||
663 | asmlinkage long sys_syslog(int type, char __user * buf, int len) | ||
664 | { | ||
665 | return 0; | ||
666 | } | ||
667 | |||
668 | int do_syslog(int type, char __user * buf, int len) { return 0; } | ||
669 | static void call_console_drivers(unsigned long start, unsigned long end) {} | ||
670 | |||
671 | #endif | ||
672 | |||
658 | /** | 673 | /** |
659 | * acquire_console_sem - lock the console system for exclusive use. | 674 | * acquire_console_sem - lock the console system for exclusive use. |
660 | * | 675 | * |
@@ -931,7 +946,7 @@ int unregister_console(struct console * console) | |||
931 | return res; | 946 | return res; |
932 | } | 947 | } |
933 | EXPORT_SYMBOL(unregister_console); | 948 | EXPORT_SYMBOL(unregister_console); |
934 | 949 | ||
935 | /** | 950 | /** |
936 | * tty_write_message - write a message to a certain tty, not just the console. | 951 | * tty_write_message - write a message to a certain tty, not just the console. |
937 | * | 952 | * |
diff --git a/kernel/profile.c b/kernel/profile.c index a38fa70075fe..0221a50ca867 100644 --- a/kernel/profile.c +++ b/kernel/profile.c | |||
@@ -184,7 +184,7 @@ void unregister_timer_hook(int (*hook)(struct pt_regs *)) | |||
184 | WARN_ON(hook != timer_hook); | 184 | WARN_ON(hook != timer_hook); |
185 | timer_hook = NULL; | 185 | timer_hook = NULL; |
186 | /* make sure all CPUs see the NULL hook */ | 186 | /* make sure all CPUs see the NULL hook */ |
187 | synchronize_kernel(); | 187 | synchronize_sched(); /* Allow ongoing interrupts to complete. */ |
188 | } | 188 | } |
189 | 189 | ||
190 | EXPORT_SYMBOL_GPL(register_timer_hook); | 190 | EXPORT_SYMBOL_GPL(register_timer_hook); |
@@ -522,7 +522,7 @@ static int __init create_hash_tables(void) | |||
522 | return 0; | 522 | return 0; |
523 | out_cleanup: | 523 | out_cleanup: |
524 | prof_on = 0; | 524 | prof_on = 0; |
525 | mb(); | 525 | smp_mb(); |
526 | on_each_cpu(profile_nop, NULL, 0, 1); | 526 | on_each_cpu(profile_nop, NULL, 0, 1); |
527 | for_each_online_cpu(cpu) { | 527 | for_each_online_cpu(cpu) { |
528 | struct page *page; | 528 | struct page *page; |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 88b306c4e841..8dcb8f6288bc 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/smp_lock.h> | 16 | #include <linux/smp_lock.h> |
17 | #include <linux/ptrace.h> | 17 | #include <linux/ptrace.h> |
18 | #include <linux/security.h> | 18 | #include <linux/security.h> |
19 | #include <linux/signal.h> | ||
19 | 20 | ||
20 | #include <asm/pgtable.h> | 21 | #include <asm/pgtable.h> |
21 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
@@ -135,7 +136,7 @@ int ptrace_attach(struct task_struct *task) | |||
135 | (current->gid != task->sgid) || | 136 | (current->gid != task->sgid) || |
136 | (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) | 137 | (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) |
137 | goto bad; | 138 | goto bad; |
138 | rmb(); | 139 | smp_rmb(); |
139 | if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) | 140 | if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) |
140 | goto bad; | 141 | goto bad; |
141 | /* the same process cannot be attached many times */ | 142 | /* the same process cannot be attached many times */ |
@@ -166,7 +167,7 @@ bad: | |||
166 | 167 | ||
167 | int ptrace_detach(struct task_struct *child, unsigned int data) | 168 | int ptrace_detach(struct task_struct *child, unsigned int data) |
168 | { | 169 | { |
169 | if ((unsigned long) data > _NSIG) | 170 | if (!valid_signal(data)) |
170 | return -EIO; | 171 | return -EIO; |
171 | 172 | ||
172 | /* Architecture-specific hardware disable .. */ | 173 | /* Architecture-specific hardware disable .. */ |
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index d00eded75d71..f436993bd590 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
@@ -444,15 +444,18 @@ static void wakeme_after_rcu(struct rcu_head *head) | |||
444 | } | 444 | } |
445 | 445 | ||
446 | /** | 446 | /** |
447 | * synchronize_kernel - wait until a grace period has elapsed. | 447 | * synchronize_rcu - wait until a grace period has elapsed. |
448 | * | 448 | * |
449 | * Control will return to the caller some time after a full grace | 449 | * Control will return to the caller some time after a full grace |
450 | * period has elapsed, in other words after all currently executing RCU | 450 | * period has elapsed, in other words after all currently executing RCU |
451 | * read-side critical sections have completed. RCU read-side critical | 451 | * read-side critical sections have completed. RCU read-side critical |
452 | * sections are delimited by rcu_read_lock() and rcu_read_unlock(), | 452 | * sections are delimited by rcu_read_lock() and rcu_read_unlock(), |
453 | * and may be nested. | 453 | * and may be nested. |
454 | * | ||
455 | * If your read-side code is not protected by rcu_read_lock(), do -not- | ||
456 | * use synchronize_rcu(). | ||
454 | */ | 457 | */ |
455 | void synchronize_kernel(void) | 458 | void synchronize_rcu(void) |
456 | { | 459 | { |
457 | struct rcu_synchronize rcu; | 460 | struct rcu_synchronize rcu; |
458 | 461 | ||
@@ -464,7 +467,16 @@ void synchronize_kernel(void) | |||
464 | wait_for_completion(&rcu.completion); | 467 | wait_for_completion(&rcu.completion); |
465 | } | 468 | } |
466 | 469 | ||
470 | /* | ||
471 | * Deprecated, use synchronize_rcu() or synchronize_sched() instead. | ||
472 | */ | ||
473 | void synchronize_kernel(void) | ||
474 | { | ||
475 | synchronize_rcu(); | ||
476 | } | ||
477 | |||
467 | module_param(maxbatch, int, 0); | 478 | module_param(maxbatch, int, 0); |
468 | EXPORT_SYMBOL_GPL(call_rcu); | 479 | EXPORT_SYMBOL(call_rcu); /* WARNING: GPL-only in April 2006. */ |
469 | EXPORT_SYMBOL_GPL(call_rcu_bh); | 480 | EXPORT_SYMBOL(call_rcu_bh); /* WARNING: GPL-only in April 2006. */ |
470 | EXPORT_SYMBOL_GPL(synchronize_kernel); | 481 | EXPORT_SYMBOL_GPL(synchronize_rcu); |
482 | EXPORT_SYMBOL(synchronize_kernel); /* WARNING: GPL-only in April 2006. */ | ||
diff --git a/kernel/sched.c b/kernel/sched.c index 9bb7489ee645..0dc3158667a2 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -2906,6 +2906,7 @@ static void __wake_up_common(wait_queue_head_t *q, unsigned int mode, | |||
2906 | * @q: the waitqueue | 2906 | * @q: the waitqueue |
2907 | * @mode: which threads | 2907 | * @mode: which threads |
2908 | * @nr_exclusive: how many wake-one or wake-many threads to wake up | 2908 | * @nr_exclusive: how many wake-one or wake-many threads to wake up |
2909 | * @key: is directly passed to the wakeup function | ||
2909 | */ | 2910 | */ |
2910 | void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode, | 2911 | void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode, |
2911 | int nr_exclusive, void *key) | 2912 | int nr_exclusive, void *key) |
@@ -2928,7 +2929,7 @@ void fastcall __wake_up_locked(wait_queue_head_t *q, unsigned int mode) | |||
2928 | } | 2929 | } |
2929 | 2930 | ||
2930 | /** | 2931 | /** |
2931 | * __wake_up - sync- wake up threads blocked on a waitqueue. | 2932 | * __wake_up_sync - wake up threads blocked on a waitqueue. |
2932 | * @q: the waitqueue | 2933 | * @q: the waitqueue |
2933 | * @mode: which threads | 2934 | * @mode: which threads |
2934 | * @nr_exclusive: how many wake-one or wake-many threads to wake up | 2935 | * @nr_exclusive: how many wake-one or wake-many threads to wake up |
@@ -3223,6 +3224,19 @@ out_unlock: | |||
3223 | 3224 | ||
3224 | EXPORT_SYMBOL(set_user_nice); | 3225 | EXPORT_SYMBOL(set_user_nice); |
3225 | 3226 | ||
3227 | /* | ||
3228 | * can_nice - check if a task can reduce its nice value | ||
3229 | * @p: task | ||
3230 | * @nice: nice value | ||
3231 | */ | ||
3232 | int can_nice(const task_t *p, const int nice) | ||
3233 | { | ||
3234 | /* convert nice value [19,-20] to rlimit style value [0,39] */ | ||
3235 | int nice_rlim = 19 - nice; | ||
3236 | return (nice_rlim <= p->signal->rlim[RLIMIT_NICE].rlim_cur || | ||
3237 | capable(CAP_SYS_NICE)); | ||
3238 | } | ||
3239 | |||
3226 | #ifdef __ARCH_WANT_SYS_NICE | 3240 | #ifdef __ARCH_WANT_SYS_NICE |
3227 | 3241 | ||
3228 | /* | 3242 | /* |
@@ -3242,12 +3256,8 @@ asmlinkage long sys_nice(int increment) | |||
3242 | * We don't have to worry. Conceptually one call occurs first | 3256 | * We don't have to worry. Conceptually one call occurs first |
3243 | * and we have a single winner. | 3257 | * and we have a single winner. |
3244 | */ | 3258 | */ |
3245 | if (increment < 0) { | 3259 | if (increment < -40) |
3246 | if (!capable(CAP_SYS_NICE)) | 3260 | increment = -40; |
3247 | return -EPERM; | ||
3248 | if (increment < -40) | ||
3249 | increment = -40; | ||
3250 | } | ||
3251 | if (increment > 40) | 3261 | if (increment > 40) |
3252 | increment = 40; | 3262 | increment = 40; |
3253 | 3263 | ||
@@ -3257,6 +3267,9 @@ asmlinkage long sys_nice(int increment) | |||
3257 | if (nice > 19) | 3267 | if (nice > 19) |
3258 | nice = 19; | 3268 | nice = 19; |
3259 | 3269 | ||
3270 | if (increment < 0 && !can_nice(current, nice)) | ||
3271 | return -EPERM; | ||
3272 | |||
3260 | retval = security_task_setnice(current, nice); | 3273 | retval = security_task_setnice(current, nice); |
3261 | if (retval) | 3274 | if (retval) |
3262 | return retval; | 3275 | return retval; |
@@ -3372,6 +3385,7 @@ recheck: | |||
3372 | return -EINVAL; | 3385 | return -EINVAL; |
3373 | 3386 | ||
3374 | if ((policy == SCHED_FIFO || policy == SCHED_RR) && | 3387 | if ((policy == SCHED_FIFO || policy == SCHED_RR) && |
3388 | param->sched_priority > p->signal->rlim[RLIMIT_RTPRIO].rlim_cur && | ||
3375 | !capable(CAP_SYS_NICE)) | 3389 | !capable(CAP_SYS_NICE)) |
3376 | return -EPERM; | 3390 | return -EPERM; |
3377 | if ((current->euid != p->euid) && (current->euid != p->uid) && | 3391 | if ((current->euid != p->euid) && (current->euid != p->uid) && |
diff --git a/kernel/signal.c b/kernel/signal.c index e6567d7f2b62..8f3debc77c5b 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/syscalls.h> | 23 | #include <linux/syscalls.h> |
24 | #include <linux/ptrace.h> | 24 | #include <linux/ptrace.h> |
25 | #include <linux/posix-timers.h> | 25 | #include <linux/posix-timers.h> |
26 | #include <linux/signal.h> | ||
26 | #include <asm/param.h> | 27 | #include <asm/param.h> |
27 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
28 | #include <asm/unistd.h> | 29 | #include <asm/unistd.h> |
@@ -646,7 +647,7 @@ static int check_kill_permission(int sig, struct siginfo *info, | |||
646 | struct task_struct *t) | 647 | struct task_struct *t) |
647 | { | 648 | { |
648 | int error = -EINVAL; | 649 | int error = -EINVAL; |
649 | if (sig < 0 || sig > _NSIG) | 650 | if (!valid_signal(sig)) |
650 | return error; | 651 | return error; |
651 | error = -EPERM; | 652 | error = -EPERM; |
652 | if ((!info || ((unsigned long)info != 1 && | 653 | if ((!info || ((unsigned long)info != 1 && |
@@ -1245,7 +1246,7 @@ send_sig_info(int sig, struct siginfo *info, struct task_struct *p) | |||
1245 | * Make sure legacy kernel users don't send in bad values | 1246 | * Make sure legacy kernel users don't send in bad values |
1246 | * (normal paths check this in check_kill_permission). | 1247 | * (normal paths check this in check_kill_permission). |
1247 | */ | 1248 | */ |
1248 | if (sig < 0 || sig > _NSIG) | 1249 | if (!valid_signal(sig)) |
1249 | return -EINVAL; | 1250 | return -EINVAL; |
1250 | 1251 | ||
1251 | /* | 1252 | /* |
@@ -1520,7 +1521,7 @@ void do_notify_parent(struct task_struct *tsk, int sig) | |||
1520 | if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) | 1521 | if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) |
1521 | sig = 0; | 1522 | sig = 0; |
1522 | } | 1523 | } |
1523 | if (sig > 0 && sig <= _NSIG) | 1524 | if (valid_signal(sig) && sig > 0) |
1524 | __group_send_sig_info(sig, &info, tsk->parent); | 1525 | __group_send_sig_info(sig, &info, tsk->parent); |
1525 | __wake_up_parent(tsk, tsk->parent); | 1526 | __wake_up_parent(tsk, tsk->parent); |
1526 | spin_unlock_irqrestore(&psig->siglock, flags); | 1527 | spin_unlock_irqrestore(&psig->siglock, flags); |
@@ -2364,7 +2365,7 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) | |||
2364 | { | 2365 | { |
2365 | struct k_sigaction *k; | 2366 | struct k_sigaction *k; |
2366 | 2367 | ||
2367 | if (sig < 1 || sig > _NSIG || (act && sig_kernel_only(sig))) | 2368 | if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig))) |
2368 | return -EINVAL; | 2369 | return -EINVAL; |
2369 | 2370 | ||
2370 | k = ¤t->sighand->action[sig-1]; | 2371 | k = ¤t->sighand->action[sig-1]; |
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index c39ed70af174..6116b25aa7cf 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c | |||
@@ -33,7 +33,7 @@ static int stopmachine(void *cpu) | |||
33 | set_cpus_allowed(current, cpumask_of_cpu((int)(long)cpu)); | 33 | set_cpus_allowed(current, cpumask_of_cpu((int)(long)cpu)); |
34 | 34 | ||
35 | /* Ack: we are alive */ | 35 | /* Ack: we are alive */ |
36 | mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */ | 36 | smp_mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */ |
37 | atomic_inc(&stopmachine_thread_ack); | 37 | atomic_inc(&stopmachine_thread_ack); |
38 | 38 | ||
39 | /* Simple state machine */ | 39 | /* Simple state machine */ |
@@ -43,14 +43,14 @@ static int stopmachine(void *cpu) | |||
43 | local_irq_disable(); | 43 | local_irq_disable(); |
44 | irqs_disabled = 1; | 44 | irqs_disabled = 1; |
45 | /* Ack: irqs disabled. */ | 45 | /* Ack: irqs disabled. */ |
46 | mb(); /* Must read state first. */ | 46 | smp_mb(); /* Must read state first. */ |
47 | atomic_inc(&stopmachine_thread_ack); | 47 | atomic_inc(&stopmachine_thread_ack); |
48 | } else if (stopmachine_state == STOPMACHINE_PREPARE | 48 | } else if (stopmachine_state == STOPMACHINE_PREPARE |
49 | && !prepared) { | 49 | && !prepared) { |
50 | /* Everyone is in place, hold CPU. */ | 50 | /* Everyone is in place, hold CPU. */ |
51 | preempt_disable(); | 51 | preempt_disable(); |
52 | prepared = 1; | 52 | prepared = 1; |
53 | mb(); /* Must read state first. */ | 53 | smp_mb(); /* Must read state first. */ |
54 | atomic_inc(&stopmachine_thread_ack); | 54 | atomic_inc(&stopmachine_thread_ack); |
55 | } | 55 | } |
56 | /* Yield in first stage: migration threads need to | 56 | /* Yield in first stage: migration threads need to |
@@ -62,7 +62,7 @@ static int stopmachine(void *cpu) | |||
62 | } | 62 | } |
63 | 63 | ||
64 | /* Ack: we are exiting. */ | 64 | /* Ack: we are exiting. */ |
65 | mb(); /* Must read state first. */ | 65 | smp_mb(); /* Must read state first. */ |
66 | atomic_inc(&stopmachine_thread_ack); | 66 | atomic_inc(&stopmachine_thread_ack); |
67 | 67 | ||
68 | if (irqs_disabled) | 68 | if (irqs_disabled) |
@@ -77,7 +77,7 @@ static int stopmachine(void *cpu) | |||
77 | static void stopmachine_set_state(enum stopmachine_state state) | 77 | static void stopmachine_set_state(enum stopmachine_state state) |
78 | { | 78 | { |
79 | atomic_set(&stopmachine_thread_ack, 0); | 79 | atomic_set(&stopmachine_thread_ack, 0); |
80 | wmb(); | 80 | smp_wmb(); |
81 | stopmachine_state = state; | 81 | stopmachine_state = state; |
82 | while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads) | 82 | while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads) |
83 | cpu_relax(); | 83 | cpu_relax(); |
diff --git a/kernel/sys.c b/kernel/sys.c index 462d78d55895..f006632c2ba7 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/dcookies.h> | 25 | #include <linux/dcookies.h> |
26 | #include <linux/suspend.h> | 26 | #include <linux/suspend.h> |
27 | #include <linux/tty.h> | 27 | #include <linux/tty.h> |
28 | #include <linux/signal.h> | ||
28 | 29 | ||
29 | #include <linux/compat.h> | 30 | #include <linux/compat.h> |
30 | #include <linux/syscalls.h> | 31 | #include <linux/syscalls.h> |
@@ -227,7 +228,7 @@ static int set_one_prio(struct task_struct *p, int niceval, int error) | |||
227 | error = -EPERM; | 228 | error = -EPERM; |
228 | goto out; | 229 | goto out; |
229 | } | 230 | } |
230 | if (niceval < task_nice(p) && !capable(CAP_SYS_NICE)) { | 231 | if (niceval < task_nice(p) && !can_nice(p, niceval)) { |
231 | error = -EACCES; | 232 | error = -EACCES; |
232 | goto out; | 233 | goto out; |
233 | } | 234 | } |
@@ -525,7 +526,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid) | |||
525 | if (new_egid != old_egid) | 526 | if (new_egid != old_egid) |
526 | { | 527 | { |
527 | current->mm->dumpable = 0; | 528 | current->mm->dumpable = 0; |
528 | wmb(); | 529 | smp_wmb(); |
529 | } | 530 | } |
530 | if (rgid != (gid_t) -1 || | 531 | if (rgid != (gid_t) -1 || |
531 | (egid != (gid_t) -1 && egid != old_rgid)) | 532 | (egid != (gid_t) -1 && egid != old_rgid)) |
@@ -556,7 +557,7 @@ asmlinkage long sys_setgid(gid_t gid) | |||
556 | if(old_egid != gid) | 557 | if(old_egid != gid) |
557 | { | 558 | { |
558 | current->mm->dumpable=0; | 559 | current->mm->dumpable=0; |
559 | wmb(); | 560 | smp_wmb(); |
560 | } | 561 | } |
561 | current->gid = current->egid = current->sgid = current->fsgid = gid; | 562 | current->gid = current->egid = current->sgid = current->fsgid = gid; |
562 | } | 563 | } |
@@ -565,7 +566,7 @@ asmlinkage long sys_setgid(gid_t gid) | |||
565 | if(old_egid != gid) | 566 | if(old_egid != gid) |
566 | { | 567 | { |
567 | current->mm->dumpable=0; | 568 | current->mm->dumpable=0; |
568 | wmb(); | 569 | smp_wmb(); |
569 | } | 570 | } |
570 | current->egid = current->fsgid = gid; | 571 | current->egid = current->fsgid = gid; |
571 | } | 572 | } |
@@ -596,7 +597,7 @@ static int set_user(uid_t new_ruid, int dumpclear) | |||
596 | if(dumpclear) | 597 | if(dumpclear) |
597 | { | 598 | { |
598 | current->mm->dumpable = 0; | 599 | current->mm->dumpable = 0; |
599 | wmb(); | 600 | smp_wmb(); |
600 | } | 601 | } |
601 | current->uid = new_ruid; | 602 | current->uid = new_ruid; |
602 | return 0; | 603 | return 0; |
@@ -653,7 +654,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) | |||
653 | if (new_euid != old_euid) | 654 | if (new_euid != old_euid) |
654 | { | 655 | { |
655 | current->mm->dumpable=0; | 656 | current->mm->dumpable=0; |
656 | wmb(); | 657 | smp_wmb(); |
657 | } | 658 | } |
658 | current->fsuid = current->euid = new_euid; | 659 | current->fsuid = current->euid = new_euid; |
659 | if (ruid != (uid_t) -1 || | 660 | if (ruid != (uid_t) -1 || |
@@ -703,7 +704,7 @@ asmlinkage long sys_setuid(uid_t uid) | |||
703 | if (old_euid != uid) | 704 | if (old_euid != uid) |
704 | { | 705 | { |
705 | current->mm->dumpable = 0; | 706 | current->mm->dumpable = 0; |
706 | wmb(); | 707 | smp_wmb(); |
707 | } | 708 | } |
708 | current->fsuid = current->euid = uid; | 709 | current->fsuid = current->euid = uid; |
709 | current->suid = new_suid; | 710 | current->suid = new_suid; |
@@ -748,7 +749,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) | |||
748 | if (euid != current->euid) | 749 | if (euid != current->euid) |
749 | { | 750 | { |
750 | current->mm->dumpable = 0; | 751 | current->mm->dumpable = 0; |
751 | wmb(); | 752 | smp_wmb(); |
752 | } | 753 | } |
753 | current->euid = euid; | 754 | current->euid = euid; |
754 | } | 755 | } |
@@ -798,7 +799,7 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) | |||
798 | if (egid != current->egid) | 799 | if (egid != current->egid) |
799 | { | 800 | { |
800 | current->mm->dumpable = 0; | 801 | current->mm->dumpable = 0; |
801 | wmb(); | 802 | smp_wmb(); |
802 | } | 803 | } |
803 | current->egid = egid; | 804 | current->egid = egid; |
804 | } | 805 | } |
@@ -845,7 +846,7 @@ asmlinkage long sys_setfsuid(uid_t uid) | |||
845 | if (uid != old_fsuid) | 846 | if (uid != old_fsuid) |
846 | { | 847 | { |
847 | current->mm->dumpable = 0; | 848 | current->mm->dumpable = 0; |
848 | wmb(); | 849 | smp_wmb(); |
849 | } | 850 | } |
850 | current->fsuid = uid; | 851 | current->fsuid = uid; |
851 | } | 852 | } |
@@ -875,7 +876,7 @@ asmlinkage long sys_setfsgid(gid_t gid) | |||
875 | if (gid != old_fsgid) | 876 | if (gid != old_fsgid) |
876 | { | 877 | { |
877 | current->mm->dumpable = 0; | 878 | current->mm->dumpable = 0; |
878 | wmb(); | 879 | smp_wmb(); |
879 | } | 880 | } |
880 | current->fsgid = gid; | 881 | current->fsgid = gid; |
881 | key_fsgid_changed(current); | 882 | key_fsgid_changed(current); |
@@ -1194,7 +1195,7 @@ static int groups_from_user(struct group_info *group_info, | |||
1194 | return 0; | 1195 | return 0; |
1195 | } | 1196 | } |
1196 | 1197 | ||
1197 | /* a simple shell-metzner sort */ | 1198 | /* a simple Shell sort */ |
1198 | static void groups_sort(struct group_info *group_info) | 1199 | static void groups_sort(struct group_info *group_info) |
1199 | { | 1200 | { |
1200 | int base, max, stride; | 1201 | int base, max, stride; |
@@ -1637,7 +1638,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
1637 | switch (option) { | 1638 | switch (option) { |
1638 | case PR_SET_PDEATHSIG: | 1639 | case PR_SET_PDEATHSIG: |
1639 | sig = arg2; | 1640 | sig = arg2; |
1640 | if (sig < 0 || sig > _NSIG) { | 1641 | if (!valid_signal(sig)) { |
1641 | error = -EINVAL; | 1642 | error = -EINVAL; |
1642 | break; | 1643 | break; |
1643 | } | 1644 | } |
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 1802a311dd3f..0dda70ed1f98 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c | |||
@@ -52,6 +52,7 @@ cond_syscall(sys_msgsnd); | |||
52 | cond_syscall(sys_msgrcv); | 52 | cond_syscall(sys_msgrcv); |
53 | cond_syscall(sys_msgctl); | 53 | cond_syscall(sys_msgctl); |
54 | cond_syscall(sys_shmget); | 54 | cond_syscall(sys_shmget); |
55 | cond_syscall(sys_shmat); | ||
55 | cond_syscall(sys_shmdt); | 56 | cond_syscall(sys_shmdt); |
56 | cond_syscall(sys_shmctl); | 57 | cond_syscall(sys_shmctl); |
57 | cond_syscall(sys_mq_open); | 58 | cond_syscall(sys_mq_open); |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 79dbd93bd697..701d12c63068 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -1991,6 +1991,8 @@ int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp, | |||
1991 | * @filp: the file structure | 1991 | * @filp: the file structure |
1992 | * @buffer: the user buffer | 1992 | * @buffer: the user buffer |
1993 | * @lenp: the size of the user buffer | 1993 | * @lenp: the size of the user buffer |
1994 | * @ppos: file position | ||
1995 | * @ppos: the current position in the file | ||
1994 | * | 1996 | * |
1995 | * Reads/writes up to table->maxlen/sizeof(unsigned int) integer | 1997 | * Reads/writes up to table->maxlen/sizeof(unsigned int) integer |
1996 | * values from/to the user buffer, treated as an ASCII string. | 1998 | * values from/to the user buffer, treated as an ASCII string. |
diff --git a/kernel/time.c b/kernel/time.c index 96fd0f499631..d4335c1c884c 100644 --- a/kernel/time.c +++ b/kernel/time.c | |||
@@ -516,14 +516,6 @@ int do_settimeofday (struct timespec *tv) | |||
516 | 516 | ||
517 | write_seqlock_irq(&xtime_lock); | 517 | write_seqlock_irq(&xtime_lock); |
518 | { | 518 | { |
519 | /* | ||
520 | * This is revolting. We need to set "xtime" correctly. However, the value | ||
521 | * in this location is the value at the most recent update of wall time. | ||
522 | * Discover what correction gettimeofday would have done, and then undo | ||
523 | * it! | ||
524 | */ | ||
525 | nsec -= time_interpolator_get_offset(); | ||
526 | |||
527 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); | 519 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); |
528 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); | 520 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); |
529 | 521 | ||
diff --git a/kernel/timer.c b/kernel/timer.c index ecb3d67c0e14..207aa4f0aa10 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -1007,7 +1007,7 @@ asmlinkage long sys_getppid(void) | |||
1007 | * Make sure we read the pid before re-reading the | 1007 | * Make sure we read the pid before re-reading the |
1008 | * parent pointer: | 1008 | * parent pointer: |
1009 | */ | 1009 | */ |
1010 | rmb(); | 1010 | smp_rmb(); |
1011 | parent = me->group_leader->real_parent; | 1011 | parent = me->group_leader->real_parent; |
1012 | if (old != parent) | 1012 | if (old != parent) |
1013 | continue; | 1013 | continue; |