diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/audit.c | 2 | ||||
-rw-r--r-- | kernel/cpuset.c | 13 | ||||
-rw-r--r-- | kernel/exit.c | 2 | ||||
-rw-r--r-- | kernel/kfifo.c | 4 | ||||
-rw-r--r-- | kernel/params.c | 10 | ||||
-rw-r--r-- | kernel/posix-cpu-timers.c | 3 | ||||
-rw-r--r-- | kernel/power/power.h | 5 | ||||
-rw-r--r-- | kernel/power/swsusp.c | 24 | ||||
-rw-r--r-- | kernel/rcupdate.c | 13 | ||||
-rw-r--r-- | kernel/signal.c | 73 | ||||
-rw-r--r-- | kernel/time.c | 1 |
11 files changed, 101 insertions, 49 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index 83096b67510a..aefa73a8a586 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -560,7 +560,7 @@ static void audit_buffer_free(struct audit_buffer *ab) | |||
560 | } | 560 | } |
561 | 561 | ||
562 | static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, | 562 | static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, |
563 | unsigned int __nocast gfp_mask, int type) | 563 | gfp_t gfp_mask, int type) |
564 | { | 564 | { |
565 | unsigned long flags; | 565 | unsigned long flags; |
566 | struct audit_buffer *ab = NULL; | 566 | struct audit_buffer *ab = NULL; |
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 79866bc6b3a1..28176d083f7b 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -968,8 +968,6 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf, | |||
968 | char *page; | 968 | char *page; |
969 | ssize_t retval = 0; | 969 | ssize_t retval = 0; |
970 | char *s; | 970 | char *s; |
971 | char *start; | ||
972 | size_t n; | ||
973 | 971 | ||
974 | if (!(page = (char *)__get_free_page(GFP_KERNEL))) | 972 | if (!(page = (char *)__get_free_page(GFP_KERNEL))) |
975 | return -ENOMEM; | 973 | return -ENOMEM; |
@@ -999,14 +997,7 @@ static ssize_t cpuset_common_file_read(struct file *file, char __user *buf, | |||
999 | *s++ = '\n'; | 997 | *s++ = '\n'; |
1000 | *s = '\0'; | 998 | *s = '\0'; |
1001 | 999 | ||
1002 | /* Do nothing if *ppos is at the eof or beyond the eof. */ | 1000 | retval = simple_read_from_buffer(buf, nbytes, ppos, page, s - page); |
1003 | if (s - page <= *ppos) | ||
1004 | return 0; | ||
1005 | |||
1006 | start = page + *ppos; | ||
1007 | n = s - start; | ||
1008 | retval = n - copy_to_user(buf, start, min(n, nbytes)); | ||
1009 | *ppos += retval; | ||
1010 | out: | 1001 | out: |
1011 | free_page((unsigned long)page); | 1002 | free_page((unsigned long)page); |
1012 | return retval; | 1003 | return retval; |
@@ -1679,7 +1670,7 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs) | |||
1679 | * GFP_USER - only nodes in current tasks mems allowed ok. | 1670 | * GFP_USER - only nodes in current tasks mems allowed ok. |
1680 | **/ | 1671 | **/ |
1681 | 1672 | ||
1682 | int cpuset_zone_allowed(struct zone *z, unsigned int __nocast gfp_mask) | 1673 | int cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) |
1683 | { | 1674 | { |
1684 | int node; /* node that zone z is on */ | 1675 | int node; /* node that zone z is on */ |
1685 | const struct cpuset *cs; /* current cpuset ancestors */ | 1676 | const struct cpuset *cs; /* current cpuset ancestors */ |
diff --git a/kernel/exit.c b/kernel/exit.c index ee6d8b8abef5..43077732619b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -1203,7 +1203,7 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader, int noreap, | |||
1203 | 1203 | ||
1204 | exit_code = p->exit_code; | 1204 | exit_code = p->exit_code; |
1205 | if (unlikely(!exit_code) || | 1205 | if (unlikely(!exit_code) || |
1206 | unlikely(p->state > TASK_STOPPED)) | 1206 | unlikely(p->state & TASK_TRACED)) |
1207 | goto bail_ref; | 1207 | goto bail_ref; |
1208 | return wait_noreap_copyout(p, pid, uid, | 1208 | return wait_noreap_copyout(p, pid, uid, |
1209 | why, (exit_code << 8) | 0x7f, | 1209 | why, (exit_code << 8) | 0x7f, |
diff --git a/kernel/kfifo.c b/kernel/kfifo.c index 179baafcdd96..64ab045c3d9d 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c | |||
@@ -36,7 +36,7 @@ | |||
36 | * struct kfifo with kfree(). | 36 | * struct kfifo with kfree(). |
37 | */ | 37 | */ |
38 | struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size, | 38 | struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size, |
39 | unsigned int __nocast gfp_mask, spinlock_t *lock) | 39 | gfp_t gfp_mask, spinlock_t *lock) |
40 | { | 40 | { |
41 | struct kfifo *fifo; | 41 | struct kfifo *fifo; |
42 | 42 | ||
@@ -64,7 +64,7 @@ EXPORT_SYMBOL(kfifo_init); | |||
64 | * | 64 | * |
65 | * The size will be rounded-up to a power of 2. | 65 | * The size will be rounded-up to a power of 2. |
66 | */ | 66 | */ |
67 | struct kfifo *kfifo_alloc(unsigned int size, unsigned int __nocast gfp_mask, spinlock_t *lock) | 67 | struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock) |
68 | { | 68 | { |
69 | unsigned char *buffer; | 69 | unsigned char *buffer; |
70 | struct kfifo *ret; | 70 | struct kfifo *ret; |
diff --git a/kernel/params.c b/kernel/params.c index fbf173215fd2..1a8614bac5d5 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -80,8 +80,6 @@ static char *next_arg(char *args, char **param, char **val) | |||
80 | int in_quote = 0, quoted = 0; | 80 | int in_quote = 0, quoted = 0; |
81 | char *next; | 81 | char *next; |
82 | 82 | ||
83 | /* Chew any extra spaces */ | ||
84 | while (*args == ' ') args++; | ||
85 | if (*args == '"') { | 83 | if (*args == '"') { |
86 | args++; | 84 | args++; |
87 | in_quote = 1; | 85 | in_quote = 1; |
@@ -121,6 +119,10 @@ static char *next_arg(char *args, char **param, char **val) | |||
121 | next = args + i + 1; | 119 | next = args + i + 1; |
122 | } else | 120 | } else |
123 | next = args + i; | 121 | next = args + i; |
122 | |||
123 | /* Chew up trailing spaces. */ | ||
124 | while (*next == ' ') | ||
125 | next++; | ||
124 | return next; | 126 | return next; |
125 | } | 127 | } |
126 | 128 | ||
@@ -135,6 +137,10 @@ int parse_args(const char *name, | |||
135 | 137 | ||
136 | DEBUGP("Parsing ARGS: %s\n", args); | 138 | DEBUGP("Parsing ARGS: %s\n", args); |
137 | 139 | ||
140 | /* Chew leading spaces */ | ||
141 | while (*args == ' ') | ||
142 | args++; | ||
143 | |||
138 | while (*args) { | 144 | while (*args) { |
139 | int ret; | 145 | int ret; |
140 | 146 | ||
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index ad85d3f0dcc4..7a51a5597c33 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
@@ -424,6 +424,7 @@ static void cleanup_timers(struct list_head *head, | |||
424 | cputime_t ptime = cputime_add(utime, stime); | 424 | cputime_t ptime = cputime_add(utime, stime); |
425 | 425 | ||
426 | list_for_each_entry_safe(timer, next, head, entry) { | 426 | list_for_each_entry_safe(timer, next, head, entry) { |
427 | put_task_struct(timer->task); | ||
427 | timer->task = NULL; | 428 | timer->task = NULL; |
428 | list_del_init(&timer->entry); | 429 | list_del_init(&timer->entry); |
429 | if (cputime_lt(timer->expires.cpu, ptime)) { | 430 | if (cputime_lt(timer->expires.cpu, ptime)) { |
@@ -436,6 +437,7 @@ static void cleanup_timers(struct list_head *head, | |||
436 | 437 | ||
437 | ++head; | 438 | ++head; |
438 | list_for_each_entry_safe(timer, next, head, entry) { | 439 | list_for_each_entry_safe(timer, next, head, entry) { |
440 | put_task_struct(timer->task); | ||
439 | timer->task = NULL; | 441 | timer->task = NULL; |
440 | list_del_init(&timer->entry); | 442 | list_del_init(&timer->entry); |
441 | if (cputime_lt(timer->expires.cpu, utime)) { | 443 | if (cputime_lt(timer->expires.cpu, utime)) { |
@@ -448,6 +450,7 @@ static void cleanup_timers(struct list_head *head, | |||
448 | 450 | ||
449 | ++head; | 451 | ++head; |
450 | list_for_each_entry_safe(timer, next, head, entry) { | 452 | list_for_each_entry_safe(timer, next, head, entry) { |
453 | put_task_struct(timer->task); | ||
451 | timer->task = NULL; | 454 | timer->task = NULL; |
452 | list_del_init(&timer->entry); | 455 | list_del_init(&timer->entry); |
453 | if (timer->expires.sched < sched_time) { | 456 | if (timer->expires.sched < sched_time) { |
diff --git a/kernel/power/power.h b/kernel/power/power.h index 9c9167d910dd..6748de23e83c 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h | |||
@@ -9,6 +9,9 @@ | |||
9 | #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) | 9 | #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) |
10 | #endif | 10 | #endif |
11 | 11 | ||
12 | #define MAX_PBES ((PAGE_SIZE - sizeof(struct new_utsname) \ | ||
13 | - 4 - 3*sizeof(unsigned long) - sizeof(int) \ | ||
14 | - sizeof(void *)) / sizeof(swp_entry_t)) | ||
12 | 15 | ||
13 | struct swsusp_info { | 16 | struct swsusp_info { |
14 | struct new_utsname uts; | 17 | struct new_utsname uts; |
@@ -18,7 +21,7 @@ struct swsusp_info { | |||
18 | unsigned long image_pages; | 21 | unsigned long image_pages; |
19 | unsigned long pagedir_pages; | 22 | unsigned long pagedir_pages; |
20 | suspend_pagedir_t * suspend_pagedir; | 23 | suspend_pagedir_t * suspend_pagedir; |
21 | swp_entry_t pagedir[768]; | 24 | swp_entry_t pagedir[MAX_PBES]; |
22 | } __attribute__((aligned(PAGE_SIZE))); | 25 | } __attribute__((aligned(PAGE_SIZE))); |
23 | 26 | ||
24 | 27 | ||
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index 1cc9ff25e479..2d5c45676442 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c | |||
@@ -402,15 +402,14 @@ static int write_page(unsigned long addr, swp_entry_t * loc) | |||
402 | static void data_free(void) | 402 | static void data_free(void) |
403 | { | 403 | { |
404 | swp_entry_t entry; | 404 | swp_entry_t entry; |
405 | int i; | 405 | struct pbe * p; |
406 | 406 | ||
407 | for (i = 0; i < nr_copy_pages; i++) { | 407 | for_each_pbe(p, pagedir_nosave) { |
408 | entry = (pagedir_nosave + i)->swap_address; | 408 | entry = p->swap_address; |
409 | if (entry.val) | 409 | if (entry.val) |
410 | swap_free(entry); | 410 | swap_free(entry); |
411 | else | 411 | else |
412 | break; | 412 | break; |
413 | (pagedir_nosave + i)->swap_address = (swp_entry_t){0}; | ||
414 | } | 413 | } |
415 | } | 414 | } |
416 | 415 | ||
@@ -932,6 +931,10 @@ static int swsusp_alloc(void) | |||
932 | if (!enough_swap()) | 931 | if (!enough_swap()) |
933 | return -ENOSPC; | 932 | return -ENOSPC; |
934 | 933 | ||
934 | if (MAX_PBES < nr_copy_pages / PBES_PER_PAGE + | ||
935 | !!(nr_copy_pages % PBES_PER_PAGE)) | ||
936 | return -ENOSPC; | ||
937 | |||
935 | if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) { | 938 | if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) { |
936 | printk(KERN_ERR "suspend: Allocating pagedir failed.\n"); | 939 | printk(KERN_ERR "suspend: Allocating pagedir failed.\n"); |
937 | return -ENOMEM; | 940 | return -ENOMEM; |
@@ -1092,7 +1095,7 @@ static inline void eat_page(void *page) | |||
1092 | *eaten_memory = c; | 1095 | *eaten_memory = c; |
1093 | } | 1096 | } |
1094 | 1097 | ||
1095 | static unsigned long get_usable_page(unsigned gfp_mask) | 1098 | unsigned long get_usable_page(unsigned gfp_mask) |
1096 | { | 1099 | { |
1097 | unsigned long m; | 1100 | unsigned long m; |
1098 | 1101 | ||
@@ -1106,7 +1109,7 @@ static unsigned long get_usable_page(unsigned gfp_mask) | |||
1106 | return m; | 1109 | return m; |
1107 | } | 1110 | } |
1108 | 1111 | ||
1109 | static void free_eaten_memory(void) | 1112 | void free_eaten_memory(void) |
1110 | { | 1113 | { |
1111 | unsigned long m; | 1114 | unsigned long m; |
1112 | void **c; | 1115 | void **c; |
@@ -1438,9 +1441,9 @@ static int read_pagedir(struct pbe *pblist) | |||
1438 | } | 1441 | } |
1439 | 1442 | ||
1440 | if (error) | 1443 | if (error) |
1441 | free_page((unsigned long)pblist); | 1444 | free_pagedir(pblist); |
1442 | 1445 | else | |
1443 | BUG_ON(i != swsusp_info.pagedir_pages); | 1446 | BUG_ON(i != swsusp_info.pagedir_pages); |
1444 | 1447 | ||
1445 | return error; | 1448 | return error; |
1446 | } | 1449 | } |
@@ -1478,11 +1481,12 @@ static int read_suspend_image(void) | |||
1478 | /* Allocate memory for the image and read the data from swap */ | 1481 | /* Allocate memory for the image and read the data from swap */ |
1479 | 1482 | ||
1480 | error = check_pagedir(pagedir_nosave); | 1483 | error = check_pagedir(pagedir_nosave); |
1481 | free_eaten_memory(); | 1484 | |
1482 | if (!error) | 1485 | if (!error) |
1483 | error = data_read(pagedir_nosave); | 1486 | error = data_read(pagedir_nosave); |
1484 | 1487 | ||
1485 | if (error) { /* We fail cleanly */ | 1488 | if (error) { /* We fail cleanly */ |
1489 | free_eaten_memory(); | ||
1486 | for_each_pbe (p, pagedir_nosave) | 1490 | for_each_pbe (p, pagedir_nosave) |
1487 | if (p->address) { | 1491 | if (p->address) { |
1488 | free_page(p->address); | 1492 | free_page(p->address); |
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index bef3b6901b76..2559d4b8f23f 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
@@ -71,7 +71,7 @@ DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L }; | |||
71 | 71 | ||
72 | /* Fake initialization required by compiler */ | 72 | /* Fake initialization required by compiler */ |
73 | static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL}; | 73 | static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL}; |
74 | static int maxbatch = 10; | 74 | static int maxbatch = 10000; |
75 | 75 | ||
76 | #ifndef __HAVE_ARCH_CMPXCHG | 76 | #ifndef __HAVE_ARCH_CMPXCHG |
77 | /* | 77 | /* |
@@ -109,6 +109,10 @@ void fastcall call_rcu(struct rcu_head *head, | |||
109 | rdp = &__get_cpu_var(rcu_data); | 109 | rdp = &__get_cpu_var(rcu_data); |
110 | *rdp->nxttail = head; | 110 | *rdp->nxttail = head; |
111 | rdp->nxttail = &head->next; | 111 | rdp->nxttail = &head->next; |
112 | |||
113 | if (unlikely(++rdp->count > 10000)) | ||
114 | set_need_resched(); | ||
115 | |||
112 | local_irq_restore(flags); | 116 | local_irq_restore(flags); |
113 | } | 117 | } |
114 | 118 | ||
@@ -140,6 +144,12 @@ void fastcall call_rcu_bh(struct rcu_head *head, | |||
140 | rdp = &__get_cpu_var(rcu_bh_data); | 144 | rdp = &__get_cpu_var(rcu_bh_data); |
141 | *rdp->nxttail = head; | 145 | *rdp->nxttail = head; |
142 | rdp->nxttail = &head->next; | 146 | rdp->nxttail = &head->next; |
147 | rdp->count++; | ||
148 | /* | ||
149 | * Should we directly call rcu_do_batch() here ? | ||
150 | * if (unlikely(rdp->count > 10000)) | ||
151 | * rcu_do_batch(rdp); | ||
152 | */ | ||
143 | local_irq_restore(flags); | 153 | local_irq_restore(flags); |
144 | } | 154 | } |
145 | 155 | ||
@@ -157,6 +167,7 @@ static void rcu_do_batch(struct rcu_data *rdp) | |||
157 | next = rdp->donelist = list->next; | 167 | next = rdp->donelist = list->next; |
158 | list->func(list); | 168 | list->func(list); |
159 | list = next; | 169 | list = next; |
170 | rdp->count--; | ||
160 | if (++count >= maxbatch) | 171 | if (++count >= maxbatch) |
161 | break; | 172 | break; |
162 | } | 173 | } |
diff --git a/kernel/signal.c b/kernel/signal.c index b92c3c9f8b9a..50c992643771 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -262,7 +262,7 @@ next_signal(struct sigpending *pending, sigset_t *mask) | |||
262 | return sig; | 262 | return sig; |
263 | } | 263 | } |
264 | 264 | ||
265 | static struct sigqueue *__sigqueue_alloc(struct task_struct *t, unsigned int __nocast flags, | 265 | static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags, |
266 | int override_rlimit) | 266 | int override_rlimit) |
267 | { | 267 | { |
268 | struct sigqueue *q = NULL; | 268 | struct sigqueue *q = NULL; |
@@ -578,7 +578,8 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) | |||
578 | * is to alert stop-signal processing code when another | 578 | * is to alert stop-signal processing code when another |
579 | * processor has come along and cleared the flag. | 579 | * processor has come along and cleared the flag. |
580 | */ | 580 | */ |
581 | tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; | 581 | if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) |
582 | tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; | ||
582 | } | 583 | } |
583 | if ( signr && | 584 | if ( signr && |
584 | ((info->si_code & __SI_MASK) == __SI_TIMER) && | 585 | ((info->si_code & __SI_MASK) == __SI_TIMER) && |
@@ -936,34 +937,31 @@ force_sig_specific(int sig, struct task_struct *t) | |||
936 | * as soon as they're available, so putting the signal on the shared queue | 937 | * as soon as they're available, so putting the signal on the shared queue |
937 | * will be equivalent to sending it to one such thread. | 938 | * will be equivalent to sending it to one such thread. |
938 | */ | 939 | */ |
939 | #define wants_signal(sig, p, mask) \ | 940 | static inline int wants_signal(int sig, struct task_struct *p) |
940 | (!sigismember(&(p)->blocked, sig) \ | 941 | { |
941 | && !((p)->state & mask) \ | 942 | if (sigismember(&p->blocked, sig)) |
942 | && !((p)->flags & PF_EXITING) \ | 943 | return 0; |
943 | && (task_curr(p) || !signal_pending(p))) | 944 | if (p->flags & PF_EXITING) |
944 | 945 | return 0; | |
946 | if (sig == SIGKILL) | ||
947 | return 1; | ||
948 | if (p->state & (TASK_STOPPED | TASK_TRACED)) | ||
949 | return 0; | ||
950 | return task_curr(p) || !signal_pending(p); | ||
951 | } | ||
945 | 952 | ||
946 | static void | 953 | static void |
947 | __group_complete_signal(int sig, struct task_struct *p) | 954 | __group_complete_signal(int sig, struct task_struct *p) |
948 | { | 955 | { |
949 | unsigned int mask; | ||
950 | struct task_struct *t; | 956 | struct task_struct *t; |
951 | 957 | ||
952 | /* | 958 | /* |
953 | * Don't bother traced and stopped tasks (but | ||
954 | * SIGKILL will punch through that). | ||
955 | */ | ||
956 | mask = TASK_STOPPED | TASK_TRACED; | ||
957 | if (sig == SIGKILL) | ||
958 | mask = 0; | ||
959 | |||
960 | /* | ||
961 | * Now find a thread we can wake up to take the signal off the queue. | 959 | * Now find a thread we can wake up to take the signal off the queue. |
962 | * | 960 | * |
963 | * If the main thread wants the signal, it gets first crack. | 961 | * If the main thread wants the signal, it gets first crack. |
964 | * Probably the least surprising to the average bear. | 962 | * Probably the least surprising to the average bear. |
965 | */ | 963 | */ |
966 | if (wants_signal(sig, p, mask)) | 964 | if (wants_signal(sig, p)) |
967 | t = p; | 965 | t = p; |
968 | else if (thread_group_empty(p)) | 966 | else if (thread_group_empty(p)) |
969 | /* | 967 | /* |
@@ -981,7 +979,7 @@ __group_complete_signal(int sig, struct task_struct *p) | |||
981 | t = p->signal->curr_target = p; | 979 | t = p->signal->curr_target = p; |
982 | BUG_ON(t->tgid != p->tgid); | 980 | BUG_ON(t->tgid != p->tgid); |
983 | 981 | ||
984 | while (!wants_signal(sig, t, mask)) { | 982 | while (!wants_signal(sig, t)) { |
985 | t = next_thread(t); | 983 | t = next_thread(t); |
986 | if (t == p->signal->curr_target) | 984 | if (t == p->signal->curr_target) |
987 | /* | 985 | /* |
@@ -1195,6 +1193,40 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid) | |||
1195 | return error; | 1193 | return error; |
1196 | } | 1194 | } |
1197 | 1195 | ||
1196 | /* like kill_proc_info(), but doesn't use uid/euid of "current" */ | ||
1197 | int kill_proc_info_as_uid(int sig, struct siginfo *info, pid_t pid, | ||
1198 | uid_t uid, uid_t euid) | ||
1199 | { | ||
1200 | int ret = -EINVAL; | ||
1201 | struct task_struct *p; | ||
1202 | |||
1203 | if (!valid_signal(sig)) | ||
1204 | return ret; | ||
1205 | |||
1206 | read_lock(&tasklist_lock); | ||
1207 | p = find_task_by_pid(pid); | ||
1208 | if (!p) { | ||
1209 | ret = -ESRCH; | ||
1210 | goto out_unlock; | ||
1211 | } | ||
1212 | if ((!info || ((unsigned long)info != 1 && | ||
1213 | (unsigned long)info != 2 && SI_FROMUSER(info))) | ||
1214 | && (euid != p->suid) && (euid != p->uid) | ||
1215 | && (uid != p->suid) && (uid != p->uid)) { | ||
1216 | ret = -EPERM; | ||
1217 | goto out_unlock; | ||
1218 | } | ||
1219 | if (sig && p->sighand) { | ||
1220 | unsigned long flags; | ||
1221 | spin_lock_irqsave(&p->sighand->siglock, flags); | ||
1222 | ret = __group_send_sig_info(sig, info, p); | ||
1223 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | ||
1224 | } | ||
1225 | out_unlock: | ||
1226 | read_unlock(&tasklist_lock); | ||
1227 | return ret; | ||
1228 | } | ||
1229 | EXPORT_SYMBOL_GPL(kill_proc_info_as_uid); | ||
1198 | 1230 | ||
1199 | /* | 1231 | /* |
1200 | * kill_something_info() interprets pid in interesting ways just like kill(2). | 1232 | * kill_something_info() interprets pid in interesting ways just like kill(2). |
@@ -1766,7 +1798,8 @@ do_signal_stop(int signr) | |||
1766 | * stop is always done with the siglock held, | 1798 | * stop is always done with the siglock held, |
1767 | * so this check has no races. | 1799 | * so this check has no races. |
1768 | */ | 1800 | */ |
1769 | if (t->state < TASK_STOPPED) { | 1801 | if (!t->exit_state && |
1802 | !(t->state & (TASK_STOPPED|TASK_TRACED))) { | ||
1770 | stop_count++; | 1803 | stop_count++; |
1771 | signal_wake_up(t, 0); | 1804 | signal_wake_up(t, 0); |
1772 | } | 1805 | } |
diff --git a/kernel/time.c b/kernel/time.c index dd5ae1162a8f..40c2410ac99a 100644 --- a/kernel/time.c +++ b/kernel/time.c | |||
@@ -570,6 +570,7 @@ void getnstimeofday(struct timespec *tv) | |||
570 | tv->tv_sec = x.tv_sec; | 570 | tv->tv_sec = x.tv_sec; |
571 | tv->tv_nsec = x.tv_usec * NSEC_PER_USEC; | 571 | tv->tv_nsec = x.tv_usec * NSEC_PER_USEC; |
572 | } | 572 | } |
573 | EXPORT_SYMBOL_GPL(getnstimeofday); | ||
573 | #endif | 574 | #endif |
574 | 575 | ||
575 | #if (BITS_PER_LONG < 64) | 576 | #if (BITS_PER_LONG < 64) |