diff options
Diffstat (limited to 'kernel/auditsc.c')
| -rw-r--r-- | kernel/auditsc.c | 133 |
1 files changed, 66 insertions, 67 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 9845cb32b60a..90594c9f7552 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -95,13 +95,6 @@ struct audit_aux_data { | |||
| 95 | /* Number of target pids per aux struct. */ | 95 | /* Number of target pids per aux struct. */ |
| 96 | #define AUDIT_AUX_PIDS 16 | 96 | #define AUDIT_AUX_PIDS 16 |
| 97 | 97 | ||
| 98 | struct audit_aux_data_execve { | ||
| 99 | struct audit_aux_data d; | ||
| 100 | int argc; | ||
| 101 | int envc; | ||
| 102 | struct mm_struct *mm; | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct audit_aux_data_pids { | 98 | struct audit_aux_data_pids { |
| 106 | struct audit_aux_data d; | 99 | struct audit_aux_data d; |
| 107 | pid_t target_pid[AUDIT_AUX_PIDS]; | 100 | pid_t target_pid[AUDIT_AUX_PIDS]; |
| @@ -121,12 +114,6 @@ struct audit_aux_data_bprm_fcaps { | |||
| 121 | struct audit_cap_data new_pcap; | 114 | struct audit_cap_data new_pcap; |
| 122 | }; | 115 | }; |
| 123 | 116 | ||
| 124 | struct audit_aux_data_capset { | ||
| 125 | struct audit_aux_data d; | ||
| 126 | pid_t pid; | ||
| 127 | struct audit_cap_data cap; | ||
| 128 | }; | ||
| 129 | |||
| 130 | struct audit_tree_refs { | 117 | struct audit_tree_refs { |
| 131 | struct audit_tree_refs *next; | 118 | struct audit_tree_refs *next; |
| 132 | struct audit_chunk *c[31]; | 119 | struct audit_chunk *c[31]; |
| @@ -566,7 +553,7 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 566 | break; | 553 | break; |
| 567 | case AUDIT_INODE: | 554 | case AUDIT_INODE: |
| 568 | if (name) | 555 | if (name) |
| 569 | result = (name->ino == f->val); | 556 | result = audit_comparator(name->ino, f->op, f->val); |
| 570 | else if (ctx) { | 557 | else if (ctx) { |
| 571 | list_for_each_entry(n, &ctx->names_list, list) { | 558 | list_for_each_entry(n, &ctx->names_list, list) { |
| 572 | if (audit_comparator(n->ino, f->op, f->val)) { | 559 | if (audit_comparator(n->ino, f->op, f->val)) { |
| @@ -943,8 +930,10 @@ int audit_alloc(struct task_struct *tsk) | |||
| 943 | return 0; /* Return if not auditing. */ | 930 | return 0; /* Return if not auditing. */ |
| 944 | 931 | ||
| 945 | state = audit_filter_task(tsk, &key); | 932 | state = audit_filter_task(tsk, &key); |
| 946 | if (state == AUDIT_DISABLED) | 933 | if (state == AUDIT_DISABLED) { |
| 934 | clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT); | ||
| 947 | return 0; | 935 | return 0; |
| 936 | } | ||
| 948 | 937 | ||
| 949 | if (!(context = audit_alloc_context(state))) { | 938 | if (!(context = audit_alloc_context(state))) { |
| 950 | kfree(key); | 939 | kfree(key); |
| @@ -1149,20 +1138,16 @@ static int audit_log_single_execve_arg(struct audit_context *context, | |||
| 1149 | } | 1138 | } |
| 1150 | 1139 | ||
| 1151 | static void audit_log_execve_info(struct audit_context *context, | 1140 | static void audit_log_execve_info(struct audit_context *context, |
| 1152 | struct audit_buffer **ab, | 1141 | struct audit_buffer **ab) |
| 1153 | struct audit_aux_data_execve *axi) | ||
| 1154 | { | 1142 | { |
| 1155 | int i, len; | 1143 | int i, len; |
| 1156 | size_t len_sent = 0; | 1144 | size_t len_sent = 0; |
| 1157 | const char __user *p; | 1145 | const char __user *p; |
| 1158 | char *buf; | 1146 | char *buf; |
| 1159 | 1147 | ||
| 1160 | if (axi->mm != current->mm) | 1148 | p = (const char __user *)current->mm->arg_start; |
| 1161 | return; /* execve failed, no additional info */ | ||
| 1162 | |||
| 1163 | p = (const char __user *)axi->mm->arg_start; | ||
| 1164 | 1149 | ||
| 1165 | audit_log_format(*ab, "argc=%d", axi->argc); | 1150 | audit_log_format(*ab, "argc=%d", context->execve.argc); |
| 1166 | 1151 | ||
| 1167 | /* | 1152 | /* |
| 1168 | * we need some kernel buffer to hold the userspace args. Just | 1153 | * we need some kernel buffer to hold the userspace args. Just |
| @@ -1176,7 +1161,7 @@ static void audit_log_execve_info(struct audit_context *context, | |||
| 1176 | return; | 1161 | return; |
| 1177 | } | 1162 | } |
| 1178 | 1163 | ||
| 1179 | for (i = 0; i < axi->argc; i++) { | 1164 | for (i = 0; i < context->execve.argc; i++) { |
| 1180 | len = audit_log_single_execve_arg(context, ab, i, | 1165 | len = audit_log_single_execve_arg(context, ab, i, |
| 1181 | &len_sent, p, buf); | 1166 | &len_sent, p, buf); |
| 1182 | if (len <= 0) | 1167 | if (len <= 0) |
| @@ -1279,6 +1264,9 @@ static void show_special(struct audit_context *context, int *call_panic) | |||
| 1279 | audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd, | 1264 | audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd, |
| 1280 | context->mmap.flags); | 1265 | context->mmap.flags); |
| 1281 | break; } | 1266 | break; } |
| 1267 | case AUDIT_EXECVE: { | ||
| 1268 | audit_log_execve_info(context, &ab); | ||
| 1269 | break; } | ||
| 1282 | } | 1270 | } |
| 1283 | audit_log_end(ab); | 1271 | audit_log_end(ab); |
| 1284 | } | 1272 | } |
| @@ -1325,11 +1313,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1325 | 1313 | ||
| 1326 | switch (aux->type) { | 1314 | switch (aux->type) { |
| 1327 | 1315 | ||
| 1328 | case AUDIT_EXECVE: { | ||
| 1329 | struct audit_aux_data_execve *axi = (void *)aux; | ||
| 1330 | audit_log_execve_info(context, &ab, axi); | ||
| 1331 | break; } | ||
| 1332 | |||
| 1333 | case AUDIT_BPRM_FCAPS: { | 1316 | case AUDIT_BPRM_FCAPS: { |
| 1334 | struct audit_aux_data_bprm_fcaps *axs = (void *)aux; | 1317 | struct audit_aux_data_bprm_fcaps *axs = (void *)aux; |
| 1335 | audit_log_format(ab, "fver=%x", axs->fcap_ver); | 1318 | audit_log_format(ab, "fver=%x", axs->fcap_ver); |
| @@ -1964,6 +1947,43 @@ int auditsc_get_stamp(struct audit_context *ctx, | |||
| 1964 | /* global counter which is incremented every time something logs in */ | 1947 | /* global counter which is incremented every time something logs in */ |
| 1965 | static atomic_t session_id = ATOMIC_INIT(0); | 1948 | static atomic_t session_id = ATOMIC_INIT(0); |
| 1966 | 1949 | ||
| 1950 | static int audit_set_loginuid_perm(kuid_t loginuid) | ||
| 1951 | { | ||
| 1952 | /* if we are unset, we don't need privs */ | ||
| 1953 | if (!audit_loginuid_set(current)) | ||
| 1954 | return 0; | ||
| 1955 | /* if AUDIT_FEATURE_LOGINUID_IMMUTABLE means never ever allow a change*/ | ||
| 1956 | if (is_audit_feature_set(AUDIT_FEATURE_LOGINUID_IMMUTABLE)) | ||
| 1957 | return -EPERM; | ||
| 1958 | /* it is set, you need permission */ | ||
| 1959 | if (!capable(CAP_AUDIT_CONTROL)) | ||
| 1960 | return -EPERM; | ||
| 1961 | /* reject if this is not an unset and we don't allow that */ | ||
| 1962 | if (is_audit_feature_set(AUDIT_FEATURE_ONLY_UNSET_LOGINUID) && uid_valid(loginuid)) | ||
| 1963 | return -EPERM; | ||
| 1964 | return 0; | ||
| 1965 | } | ||
| 1966 | |||
| 1967 | static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, | ||
| 1968 | unsigned int oldsessionid, unsigned int sessionid, | ||
| 1969 | int rc) | ||
| 1970 | { | ||
| 1971 | struct audit_buffer *ab; | ||
| 1972 | uid_t uid, ologinuid, nloginuid; | ||
| 1973 | |||
| 1974 | uid = from_kuid(&init_user_ns, task_uid(current)); | ||
| 1975 | ologinuid = from_kuid(&init_user_ns, koldloginuid); | ||
| 1976 | nloginuid = from_kuid(&init_user_ns, kloginuid), | ||
| 1977 | |||
| 1978 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); | ||
| 1979 | if (!ab) | ||
| 1980 | return; | ||
| 1981 | audit_log_format(ab, "pid=%d uid=%u old auid=%u new auid=%u old " | ||
| 1982 | "ses=%u new ses=%u res=%d", current->pid, uid, ologinuid, | ||
| 1983 | nloginuid, oldsessionid, sessionid, !rc); | ||
| 1984 | audit_log_end(ab); | ||
| 1985 | } | ||
| 1986 | |||
| 1967 | /** | 1987 | /** |
| 1968 | * audit_set_loginuid - set current task's audit_context loginuid | 1988 | * audit_set_loginuid - set current task's audit_context loginuid |
| 1969 | * @loginuid: loginuid value | 1989 | * @loginuid: loginuid value |
| @@ -1975,37 +1995,26 @@ static atomic_t session_id = ATOMIC_INIT(0); | |||
| 1975 | int audit_set_loginuid(kuid_t loginuid) | 1995 | int audit_set_loginuid(kuid_t loginuid) |
| 1976 | { | 1996 | { |
| 1977 | struct task_struct *task = current; | 1997 | struct task_struct *task = current; |
| 1978 | struct audit_context *context = task->audit_context; | 1998 | unsigned int oldsessionid, sessionid = (unsigned int)-1; |
| 1979 | unsigned int sessionid; | 1999 | kuid_t oldloginuid; |
| 2000 | int rc; | ||
| 1980 | 2001 | ||
| 1981 | #ifdef CONFIG_AUDIT_LOGINUID_IMMUTABLE | 2002 | oldloginuid = audit_get_loginuid(current); |
| 1982 | if (audit_loginuid_set(task)) | 2003 | oldsessionid = audit_get_sessionid(current); |
| 1983 | return -EPERM; | ||
| 1984 | #else /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */ | ||
| 1985 | if (!capable(CAP_AUDIT_CONTROL)) | ||
| 1986 | return -EPERM; | ||
| 1987 | #endif /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */ | ||
| 1988 | 2004 | ||
| 1989 | sessionid = atomic_inc_return(&session_id); | 2005 | rc = audit_set_loginuid_perm(loginuid); |
| 1990 | if (context && context->in_syscall) { | 2006 | if (rc) |
| 1991 | struct audit_buffer *ab; | 2007 | goto out; |
| 2008 | |||
| 2009 | /* are we setting or clearing? */ | ||
| 2010 | if (uid_valid(loginuid)) | ||
| 2011 | sessionid = atomic_inc_return(&session_id); | ||
| 1992 | 2012 | ||
| 1993 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); | ||
| 1994 | if (ab) { | ||
| 1995 | audit_log_format(ab, "login pid=%d uid=%u " | ||
| 1996 | "old auid=%u new auid=%u" | ||
| 1997 | " old ses=%u new ses=%u", | ||
| 1998 | task->pid, | ||
| 1999 | from_kuid(&init_user_ns, task_uid(task)), | ||
| 2000 | from_kuid(&init_user_ns, task->loginuid), | ||
| 2001 | from_kuid(&init_user_ns, loginuid), | ||
| 2002 | task->sessionid, sessionid); | ||
| 2003 | audit_log_end(ab); | ||
| 2004 | } | ||
| 2005 | } | ||
| 2006 | task->sessionid = sessionid; | 2013 | task->sessionid = sessionid; |
| 2007 | task->loginuid = loginuid; | 2014 | task->loginuid = loginuid; |
| 2008 | return 0; | 2015 | out: |
| 2016 | audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc); | ||
| 2017 | return rc; | ||
| 2009 | } | 2018 | } |
| 2010 | 2019 | ||
| 2011 | /** | 2020 | /** |
| @@ -2126,22 +2135,12 @@ void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mo | |||
| 2126 | context->ipc.has_perm = 1; | 2135 | context->ipc.has_perm = 1; |
| 2127 | } | 2136 | } |
| 2128 | 2137 | ||
| 2129 | int __audit_bprm(struct linux_binprm *bprm) | 2138 | void __audit_bprm(struct linux_binprm *bprm) |
| 2130 | { | 2139 | { |
| 2131 | struct audit_aux_data_execve *ax; | ||
| 2132 | struct audit_context *context = current->audit_context; | 2140 | struct audit_context *context = current->audit_context; |
| 2133 | 2141 | ||
| 2134 | ax = kmalloc(sizeof(*ax), GFP_KERNEL); | 2142 | context->type = AUDIT_EXECVE; |
| 2135 | if (!ax) | 2143 | context->execve.argc = bprm->argc; |
| 2136 | return -ENOMEM; | ||
| 2137 | |||
| 2138 | ax->argc = bprm->argc; | ||
| 2139 | ax->envc = bprm->envc; | ||
| 2140 | ax->mm = bprm->mm; | ||
| 2141 | ax->d.type = AUDIT_EXECVE; | ||
| 2142 | ax->d.next = context->aux; | ||
| 2143 | context->aux = (void *)ax; | ||
| 2144 | return 0; | ||
| 2145 | } | 2144 | } |
| 2146 | 2145 | ||
| 2147 | 2146 | ||
