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 | ||