diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/audit.c | 4 | ||||
| -rw-r--r-- | kernel/auditfilter.c | 26 | ||||
| -rw-r--r-- | kernel/auditsc.c | 117 | ||||
| -rw-r--r-- | kernel/signal.c | 25 |
4 files changed, 120 insertions, 52 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index d417ca1db79b..0a36091ed712 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -690,9 +690,7 @@ static const struct inotify_operations audit_inotify_ops = { | |||
| 690 | /* Initialize audit support at boot time. */ | 690 | /* Initialize audit support at boot time. */ |
| 691 | static int __init audit_init(void) | 691 | static int __init audit_init(void) |
| 692 | { | 692 | { |
| 693 | #ifdef CONFIG_AUDITSYSCALL | ||
| 694 | int i; | 693 | int i; |
| 695 | #endif | ||
| 696 | 694 | ||
| 697 | printk(KERN_INFO "audit: initializing netlink socket (%s)\n", | 695 | printk(KERN_INFO "audit: initializing netlink socket (%s)\n", |
| 698 | audit_default ? "enabled" : "disabled"); | 696 | audit_default ? "enabled" : "disabled"); |
| @@ -717,10 +715,10 @@ static int __init audit_init(void) | |||
| 717 | audit_ih = inotify_init(&audit_inotify_ops); | 715 | audit_ih = inotify_init(&audit_inotify_ops); |
| 718 | if (IS_ERR(audit_ih)) | 716 | if (IS_ERR(audit_ih)) |
| 719 | audit_panic("cannot initialize inotify handle"); | 717 | audit_panic("cannot initialize inotify handle"); |
| 718 | #endif | ||
| 720 | 719 | ||
| 721 | for (i = 0; i < AUDIT_INODE_BUCKETS; i++) | 720 | for (i = 0; i < AUDIT_INODE_BUCKETS; i++) |
| 722 | INIT_LIST_HEAD(&audit_inode_hash[i]); | 721 | INIT_LIST_HEAD(&audit_inode_hash[i]); |
| 723 | #endif | ||
| 724 | 722 | ||
| 725 | return 0; | 723 | return 0; |
| 726 | } | 724 | } |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 5b4e16276ca0..6a9a5c5a4e7d 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -442,6 +442,7 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | |||
| 442 | case AUDIT_EQUAL: | 442 | case AUDIT_EQUAL: |
| 443 | break; | 443 | break; |
| 444 | default: | 444 | default: |
| 445 | err = -EINVAL; | ||
| 445 | goto exit_free; | 446 | goto exit_free; |
| 446 | } | 447 | } |
| 447 | } | 448 | } |
| @@ -579,6 +580,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 579 | case AUDIT_EQUAL: | 580 | case AUDIT_EQUAL: |
| 580 | break; | 581 | break; |
| 581 | default: | 582 | default: |
| 583 | err = -EINVAL; | ||
| 582 | goto exit_free; | 584 | goto exit_free; |
| 583 | } | 585 | } |
| 584 | } | 586 | } |
| @@ -1134,6 +1136,14 @@ static inline int audit_add_rule(struct audit_entry *entry, | |||
| 1134 | struct audit_watch *watch = entry->rule.watch; | 1136 | struct audit_watch *watch = entry->rule.watch; |
| 1135 | struct nameidata *ndp, *ndw; | 1137 | struct nameidata *ndp, *ndw; |
| 1136 | int h, err, putnd_needed = 0; | 1138 | int h, err, putnd_needed = 0; |
| 1139 | #ifdef CONFIG_AUDITSYSCALL | ||
| 1140 | int dont_count = 0; | ||
| 1141 | |||
| 1142 | /* If either of these, don't count towards total */ | ||
| 1143 | if (entry->rule.listnr == AUDIT_FILTER_USER || | ||
| 1144 | entry->rule.listnr == AUDIT_FILTER_TYPE) | ||
| 1145 | dont_count = 1; | ||
| 1146 | #endif | ||
| 1137 | 1147 | ||
| 1138 | if (inode_f) { | 1148 | if (inode_f) { |
| 1139 | h = audit_hash_ino(inode_f->val); | 1149 | h = audit_hash_ino(inode_f->val); |
| @@ -1174,6 +1184,10 @@ static inline int audit_add_rule(struct audit_entry *entry, | |||
| 1174 | } else { | 1184 | } else { |
| 1175 | list_add_tail_rcu(&entry->list, list); | 1185 | list_add_tail_rcu(&entry->list, list); |
| 1176 | } | 1186 | } |
| 1187 | #ifdef CONFIG_AUDITSYSCALL | ||
| 1188 | if (!dont_count) | ||
| 1189 | audit_n_rules++; | ||
| 1190 | #endif | ||
| 1177 | mutex_unlock(&audit_filter_mutex); | 1191 | mutex_unlock(&audit_filter_mutex); |
| 1178 | 1192 | ||
| 1179 | if (putnd_needed) | 1193 | if (putnd_needed) |
| @@ -1198,6 +1212,14 @@ static inline int audit_del_rule(struct audit_entry *entry, | |||
| 1198 | struct audit_watch *watch, *tmp_watch = entry->rule.watch; | 1212 | struct audit_watch *watch, *tmp_watch = entry->rule.watch; |
| 1199 | LIST_HEAD(inotify_list); | 1213 | LIST_HEAD(inotify_list); |
| 1200 | int h, ret = 0; | 1214 | int h, ret = 0; |
| 1215 | #ifdef CONFIG_AUDITSYSCALL | ||
| 1216 | int dont_count = 0; | ||
| 1217 | |||
| 1218 | /* If either of these, don't count towards total */ | ||
| 1219 | if (entry->rule.listnr == AUDIT_FILTER_USER || | ||
| 1220 | entry->rule.listnr == AUDIT_FILTER_TYPE) | ||
| 1221 | dont_count = 1; | ||
| 1222 | #endif | ||
| 1201 | 1223 | ||
| 1202 | if (inode_f) { | 1224 | if (inode_f) { |
| 1203 | h = audit_hash_ino(inode_f->val); | 1225 | h = audit_hash_ino(inode_f->val); |
| @@ -1235,6 +1257,10 @@ static inline int audit_del_rule(struct audit_entry *entry, | |||
| 1235 | list_del_rcu(&e->list); | 1257 | list_del_rcu(&e->list); |
| 1236 | call_rcu(&e->rcu, audit_free_rule_rcu); | 1258 | call_rcu(&e->rcu, audit_free_rule_rcu); |
| 1237 | 1259 | ||
| 1260 | #ifdef CONFIG_AUDITSYSCALL | ||
| 1261 | if (!dont_count) | ||
| 1262 | audit_n_rules--; | ||
| 1263 | #endif | ||
| 1238 | mutex_unlock(&audit_filter_mutex); | 1264 | mutex_unlock(&audit_filter_mutex); |
| 1239 | 1265 | ||
| 1240 | if (!list_empty(&inotify_list)) | 1266 | if (!list_empty(&inotify_list)) |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index ae40ac8c39e7..efc1b74bebf3 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -85,6 +85,9 @@ extern int audit_enabled; | |||
| 85 | /* Indicates that audit should log the full pathname. */ | 85 | /* Indicates that audit should log the full pathname. */ |
| 86 | #define AUDIT_NAME_FULL -1 | 86 | #define AUDIT_NAME_FULL -1 |
| 87 | 87 | ||
| 88 | /* number of audit rules */ | ||
| 89 | int audit_n_rules; | ||
| 90 | |||
| 88 | /* When fs/namei.c:getname() is called, we store the pointer in name and | 91 | /* When fs/namei.c:getname() is called, we store the pointer in name and |
| 89 | * we don't let putname() free it (instead we free all of the saved | 92 | * we don't let putname() free it (instead we free all of the saved |
| 90 | * pointers at syscall exit time). | 93 | * pointers at syscall exit time). |
| @@ -174,6 +177,7 @@ struct audit_aux_data_path { | |||
| 174 | 177 | ||
| 175 | /* The per-task audit context. */ | 178 | /* The per-task audit context. */ |
| 176 | struct audit_context { | 179 | struct audit_context { |
| 180 | int dummy; /* must be the first element */ | ||
| 177 | int in_syscall; /* 1 if task is in a syscall */ | 181 | int in_syscall; /* 1 if task is in a syscall */ |
| 178 | enum audit_state state; | 182 | enum audit_state state; |
| 179 | unsigned int serial; /* serial number for record */ | 183 | unsigned int serial; /* serial number for record */ |
| @@ -514,7 +518,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, | |||
| 514 | context->return_valid = return_valid; | 518 | context->return_valid = return_valid; |
| 515 | context->return_code = return_code; | 519 | context->return_code = return_code; |
| 516 | 520 | ||
| 517 | if (context->in_syscall && !context->auditable) { | 521 | if (context->in_syscall && !context->dummy && !context->auditable) { |
| 518 | enum audit_state state; | 522 | enum audit_state state; |
| 519 | 523 | ||
| 520 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); | 524 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); |
| @@ -530,17 +534,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, | |||
| 530 | } | 534 | } |
| 531 | 535 | ||
| 532 | get_context: | 536 | get_context: |
| 533 | context->pid = tsk->pid; | 537 | |
| 534 | context->ppid = sys_getppid(); /* sic. tsk == current in all cases */ | ||
| 535 | context->uid = tsk->uid; | ||
| 536 | context->gid = tsk->gid; | ||
| 537 | context->euid = tsk->euid; | ||
| 538 | context->suid = tsk->suid; | ||
| 539 | context->fsuid = tsk->fsuid; | ||
| 540 | context->egid = tsk->egid; | ||
| 541 | context->sgid = tsk->sgid; | ||
| 542 | context->fsgid = tsk->fsgid; | ||
| 543 | context->personality = tsk->personality; | ||
| 544 | tsk->audit_context = NULL; | 538 | tsk->audit_context = NULL; |
| 545 | return context; | 539 | return context; |
| 546 | } | 540 | } |
| @@ -749,6 +743,17 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 749 | const char *tty; | 743 | const char *tty; |
| 750 | 744 | ||
| 751 | /* tsk == current */ | 745 | /* tsk == current */ |
| 746 | context->pid = tsk->pid; | ||
| 747 | context->ppid = sys_getppid(); /* sic. tsk == current in all cases */ | ||
| 748 | context->uid = tsk->uid; | ||
| 749 | context->gid = tsk->gid; | ||
| 750 | context->euid = tsk->euid; | ||
| 751 | context->suid = tsk->suid; | ||
| 752 | context->fsuid = tsk->fsuid; | ||
| 753 | context->egid = tsk->egid; | ||
| 754 | context->sgid = tsk->sgid; | ||
| 755 | context->fsgid = tsk->fsgid; | ||
| 756 | context->personality = tsk->personality; | ||
| 752 | 757 | ||
| 753 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); | 758 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); |
| 754 | if (!ab) | 759 | if (!ab) |
| @@ -1066,7 +1071,8 @@ void audit_syscall_entry(int arch, int major, | |||
| 1066 | context->argv[3] = a4; | 1071 | context->argv[3] = a4; |
| 1067 | 1072 | ||
| 1068 | state = context->state; | 1073 | state = context->state; |
| 1069 | if (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT) | 1074 | context->dummy = !audit_n_rules; |
| 1075 | if (!context->dummy && (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT)) | ||
| 1070 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]); | 1076 | state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]); |
| 1071 | if (likely(state == AUDIT_DISABLED)) | 1077 | if (likely(state == AUDIT_DISABLED)) |
| 1072 | return; | 1078 | return; |
| @@ -1199,14 +1205,18 @@ void audit_putname(const char *name) | |||
| 1199 | #endif | 1205 | #endif |
| 1200 | } | 1206 | } |
| 1201 | 1207 | ||
| 1202 | static void audit_inode_context(int idx, const struct inode *inode) | 1208 | /* Copy inode data into an audit_names. */ |
| 1209 | static void audit_copy_inode(struct audit_names *name, const struct inode *inode) | ||
| 1203 | { | 1210 | { |
| 1204 | struct audit_context *context = current->audit_context; | 1211 | name->ino = inode->i_ino; |
| 1205 | 1212 | name->dev = inode->i_sb->s_dev; | |
| 1206 | selinux_get_inode_sid(inode, &context->names[idx].osid); | 1213 | name->mode = inode->i_mode; |
| 1214 | name->uid = inode->i_uid; | ||
| 1215 | name->gid = inode->i_gid; | ||
| 1216 | name->rdev = inode->i_rdev; | ||
| 1217 | selinux_get_inode_sid(inode, &name->osid); | ||
| 1207 | } | 1218 | } |
| 1208 | 1219 | ||
| 1209 | |||
| 1210 | /** | 1220 | /** |
| 1211 | * audit_inode - store the inode and device from a lookup | 1221 | * audit_inode - store the inode and device from a lookup |
| 1212 | * @name: name being audited | 1222 | * @name: name being audited |
| @@ -1240,20 +1250,14 @@ void __audit_inode(const char *name, const struct inode *inode) | |||
| 1240 | ++context->ino_count; | 1250 | ++context->ino_count; |
| 1241 | #endif | 1251 | #endif |
| 1242 | } | 1252 | } |
| 1243 | context->names[idx].ino = inode->i_ino; | 1253 | audit_copy_inode(&context->names[idx], inode); |
| 1244 | context->names[idx].dev = inode->i_sb->s_dev; | ||
| 1245 | context->names[idx].mode = inode->i_mode; | ||
| 1246 | context->names[idx].uid = inode->i_uid; | ||
| 1247 | context->names[idx].gid = inode->i_gid; | ||
| 1248 | context->names[idx].rdev = inode->i_rdev; | ||
| 1249 | audit_inode_context(idx, inode); | ||
| 1250 | } | 1254 | } |
| 1251 | 1255 | ||
| 1252 | /** | 1256 | /** |
| 1253 | * audit_inode_child - collect inode info for created/removed objects | 1257 | * audit_inode_child - collect inode info for created/removed objects |
| 1254 | * @dname: inode's dentry name | 1258 | * @dname: inode's dentry name |
| 1255 | * @inode: inode being audited | 1259 | * @inode: inode being audited |
| 1256 | * @pino: inode number of dentry parent | 1260 | * @parent: inode of dentry parent |
| 1257 | * | 1261 | * |
| 1258 | * For syscalls that create or remove filesystem objects, audit_inode | 1262 | * For syscalls that create or remove filesystem objects, audit_inode |
| 1259 | * can only collect information for the filesystem object's parent. | 1263 | * can only collect information for the filesystem object's parent. |
| @@ -1264,7 +1268,7 @@ void __audit_inode(const char *name, const struct inode *inode) | |||
| 1264 | * unsuccessful attempts. | 1268 | * unsuccessful attempts. |
| 1265 | */ | 1269 | */ |
| 1266 | void __audit_inode_child(const char *dname, const struct inode *inode, | 1270 | void __audit_inode_child(const char *dname, const struct inode *inode, |
| 1267 | unsigned long pino) | 1271 | const struct inode *parent) |
| 1268 | { | 1272 | { |
| 1269 | int idx; | 1273 | int idx; |
| 1270 | struct audit_context *context = current->audit_context; | 1274 | struct audit_context *context = current->audit_context; |
| @@ -1278,7 +1282,7 @@ void __audit_inode_child(const char *dname, const struct inode *inode, | |||
| 1278 | if (!dname) | 1282 | if (!dname) |
| 1279 | goto update_context; | 1283 | goto update_context; |
| 1280 | for (idx = 0; idx < context->name_count; idx++) | 1284 | for (idx = 0; idx < context->name_count; idx++) |
| 1281 | if (context->names[idx].ino == pino) { | 1285 | if (context->names[idx].ino == parent->i_ino) { |
| 1282 | const char *name = context->names[idx].name; | 1286 | const char *name = context->names[idx].name; |
| 1283 | 1287 | ||
| 1284 | if (!name) | 1288 | if (!name) |
| @@ -1302,16 +1306,47 @@ update_context: | |||
| 1302 | context->names[idx].name_len = AUDIT_NAME_FULL; | 1306 | context->names[idx].name_len = AUDIT_NAME_FULL; |
| 1303 | context->names[idx].name_put = 0; /* don't call __putname() */ | 1307 | context->names[idx].name_put = 0; /* don't call __putname() */ |
| 1304 | 1308 | ||
| 1305 | if (inode) { | 1309 | if (!inode) |
| 1306 | context->names[idx].ino = inode->i_ino; | 1310 | context->names[idx].ino = (unsigned long)-1; |
| 1307 | context->names[idx].dev = inode->i_sb->s_dev; | 1311 | else |
| 1308 | context->names[idx].mode = inode->i_mode; | 1312 | audit_copy_inode(&context->names[idx], inode); |
| 1309 | context->names[idx].uid = inode->i_uid; | 1313 | |
| 1310 | context->names[idx].gid = inode->i_gid; | 1314 | /* A parent was not found in audit_names, so copy the inode data for the |
| 1311 | context->names[idx].rdev = inode->i_rdev; | 1315 | * provided parent. */ |
| 1312 | audit_inode_context(idx, inode); | 1316 | if (!found_name) { |
| 1313 | } else | 1317 | idx = context->name_count++; |
| 1314 | context->names[idx].ino = (unsigned long)-1; | 1318 | #if AUDIT_DEBUG |
| 1319 | context->ino_count++; | ||
| 1320 | #endif | ||
| 1321 | audit_copy_inode(&context->names[idx], parent); | ||
| 1322 | } | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | /** | ||
| 1326 | * audit_inode_update - update inode info for last collected name | ||
| 1327 | * @inode: inode being audited | ||
| 1328 | * | ||
| 1329 | * When open() is called on an existing object with the O_CREAT flag, the inode | ||
| 1330 | * data audit initially collects is incorrect. This additional hook ensures | ||
| 1331 | * audit has the inode data for the actual object to be opened. | ||
| 1332 | */ | ||
| 1333 | void __audit_inode_update(const struct inode *inode) | ||
| 1334 | { | ||
| 1335 | struct audit_context *context = current->audit_context; | ||
| 1336 | int idx; | ||
| 1337 | |||
| 1338 | if (!context->in_syscall || !inode) | ||
| 1339 | return; | ||
| 1340 | |||
| 1341 | if (context->name_count == 0) { | ||
| 1342 | context->name_count++; | ||
| 1343 | #if AUDIT_DEBUG | ||
| 1344 | context->ino_count++; | ||
| 1345 | #endif | ||
| 1346 | } | ||
| 1347 | idx = context->name_count - 1; | ||
| 1348 | |||
| 1349 | audit_copy_inode(&context->names[idx], inode); | ||
| 1315 | } | 1350 | } |
| 1316 | 1351 | ||
| 1317 | /** | 1352 | /** |
| @@ -1642,7 +1677,7 @@ int audit_bprm(struct linux_binprm *bprm) | |||
| 1642 | unsigned long p, next; | 1677 | unsigned long p, next; |
| 1643 | void *to; | 1678 | void *to; |
| 1644 | 1679 | ||
| 1645 | if (likely(!audit_enabled || !context)) | 1680 | if (likely(!audit_enabled || !context || context->dummy)) |
| 1646 | return 0; | 1681 | return 0; |
| 1647 | 1682 | ||
| 1648 | ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p, | 1683 | ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p, |
| @@ -1680,7 +1715,7 @@ int audit_socketcall(int nargs, unsigned long *args) | |||
| 1680 | struct audit_aux_data_socketcall *ax; | 1715 | struct audit_aux_data_socketcall *ax; |
| 1681 | struct audit_context *context = current->audit_context; | 1716 | struct audit_context *context = current->audit_context; |
| 1682 | 1717 | ||
| 1683 | if (likely(!context)) | 1718 | if (likely(!context || context->dummy)) |
| 1684 | return 0; | 1719 | return 0; |
| 1685 | 1720 | ||
| 1686 | ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL); | 1721 | ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL); |
| @@ -1708,7 +1743,7 @@ int audit_sockaddr(int len, void *a) | |||
| 1708 | struct audit_aux_data_sockaddr *ax; | 1743 | struct audit_aux_data_sockaddr *ax; |
| 1709 | struct audit_context *context = current->audit_context; | 1744 | struct audit_context *context = current->audit_context; |
| 1710 | 1745 | ||
| 1711 | if (likely(!context)) | 1746 | if (likely(!context || context->dummy)) |
| 1712 | return 0; | 1747 | return 0; |
| 1713 | 1748 | ||
| 1714 | ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL); | 1749 | ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL); |
diff --git a/kernel/signal.c b/kernel/signal.c index 7fe874d12fae..bfdb5686fa3e 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -791,22 +791,31 @@ out: | |||
| 791 | /* | 791 | /* |
| 792 | * Force a signal that the process can't ignore: if necessary | 792 | * Force a signal that the process can't ignore: if necessary |
| 793 | * we unblock the signal and change any SIG_IGN to SIG_DFL. | 793 | * we unblock the signal and change any SIG_IGN to SIG_DFL. |
| 794 | * | ||
| 795 | * Note: If we unblock the signal, we always reset it to SIG_DFL, | ||
| 796 | * since we do not want to have a signal handler that was blocked | ||
| 797 | * be invoked when user space had explicitly blocked it. | ||
| 798 | * | ||
| 799 | * We don't want to have recursive SIGSEGV's etc, for example. | ||
| 794 | */ | 800 | */ |
| 795 | |||
| 796 | int | 801 | int |
| 797 | force_sig_info(int sig, struct siginfo *info, struct task_struct *t) | 802 | force_sig_info(int sig, struct siginfo *info, struct task_struct *t) |
| 798 | { | 803 | { |
| 799 | unsigned long int flags; | 804 | unsigned long int flags; |
| 800 | int ret; | 805 | int ret, blocked, ignored; |
| 806 | struct k_sigaction *action; | ||
| 801 | 807 | ||
| 802 | spin_lock_irqsave(&t->sighand->siglock, flags); | 808 | spin_lock_irqsave(&t->sighand->siglock, flags); |
| 803 | if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) { | 809 | action = &t->sighand->action[sig-1]; |
| 804 | t->sighand->action[sig-1].sa.sa_handler = SIG_DFL; | 810 | ignored = action->sa.sa_handler == SIG_IGN; |
| 805 | } | 811 | blocked = sigismember(&t->blocked, sig); |
| 806 | if (sigismember(&t->blocked, sig)) { | 812 | if (blocked || ignored) { |
| 807 | sigdelset(&t->blocked, sig); | 813 | action->sa.sa_handler = SIG_DFL; |
| 814 | if (blocked) { | ||
| 815 | sigdelset(&t->blocked, sig); | ||
| 816 | recalc_sigpending_tsk(t); | ||
| 817 | } | ||
| 808 | } | 818 | } |
| 809 | recalc_sigpending_tsk(t); | ||
| 810 | ret = specific_send_sig_info(sig, info, t); | 819 | ret = specific_send_sig_info(sig, info, t); |
| 811 | spin_unlock_irqrestore(&t->sighand->siglock, flags); | 820 | spin_unlock_irqrestore(&t->sighand->siglock, flags); |
| 812 | 821 | ||
