Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

SELinux: Add selfattr hooks

Add hooks for setselfattr and getselfattr. These hooks are not very
different from their setprocattr and getprocattr equivalents, and
much of the code is shared.

Cc: selinux@vger.kernel.org
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>

authored by

Casey Schaufler and committed by
Paul Moore
762c9343 223981db

+107 -27
+107 -27
security/selinux/hooks.c
··· 6285 6285 inode_doinit_with_dentry(inode, dentry); 6286 6286 } 6287 6287 6288 - static int selinux_getprocattr(struct task_struct *p, 6289 - const char *name, char **value) 6288 + static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p, 6289 + char **value) 6290 6290 { 6291 6291 const struct task_security_struct *__tsec; 6292 6292 u32 sid; ··· 6303 6303 goto bad; 6304 6304 } 6305 6305 6306 - if (!strcmp(name, "current")) 6306 + switch (attr) { 6307 + case LSM_ATTR_CURRENT: 6307 6308 sid = __tsec->sid; 6308 - else if (!strcmp(name, "prev")) 6309 + break; 6310 + case LSM_ATTR_PREV: 6309 6311 sid = __tsec->osid; 6310 - else if (!strcmp(name, "exec")) 6312 + break; 6313 + case LSM_ATTR_EXEC: 6311 6314 sid = __tsec->exec_sid; 6312 - else if (!strcmp(name, "fscreate")) 6315 + break; 6316 + case LSM_ATTR_FSCREATE: 6313 6317 sid = __tsec->create_sid; 6314 - else if (!strcmp(name, "keycreate")) 6318 + break; 6319 + case LSM_ATTR_KEYCREATE: 6315 6320 sid = __tsec->keycreate_sid; 6316 - else if (!strcmp(name, "sockcreate")) 6321 + break; 6322 + case LSM_ATTR_SOCKCREATE: 6317 6323 sid = __tsec->sockcreate_sid; 6318 - else { 6319 - error = -EINVAL; 6324 + break; 6325 + default: 6326 + error = -EOPNOTSUPP; 6320 6327 goto bad; 6321 6328 } 6322 6329 rcu_read_unlock(); ··· 6341 6334 return error; 6342 6335 } 6343 6336 6344 - static int selinux_setprocattr(const char *name, void *value, size_t size) 6337 + static int selinux_lsm_setattr(u64 attr, void *value, size_t size) 6345 6338 { 6346 6339 struct task_security_struct *tsec; 6347 6340 struct cred *new; ··· 6352 6345 /* 6353 6346 * Basic control over ability to set these attributes at all. 6354 6347 */ 6355 - if (!strcmp(name, "exec")) 6348 + switch (attr) { 6349 + case LSM_ATTR_EXEC: 6356 6350 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, 6357 6351 PROCESS__SETEXEC, NULL); 6358 - else if (!strcmp(name, "fscreate")) 6352 + break; 6353 + case LSM_ATTR_FSCREATE: 6359 6354 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, 6360 6355 PROCESS__SETFSCREATE, NULL); 6361 - else if (!strcmp(name, "keycreate")) 6356 + break; 6357 + case LSM_ATTR_KEYCREATE: 6362 6358 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, 6363 6359 PROCESS__SETKEYCREATE, NULL); 6364 - else if (!strcmp(name, "sockcreate")) 6360 + break; 6361 + case LSM_ATTR_SOCKCREATE: 6365 6362 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, 6366 6363 PROCESS__SETSOCKCREATE, NULL); 6367 - else if (!strcmp(name, "current")) 6364 + break; 6365 + case LSM_ATTR_CURRENT: 6368 6366 error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS, 6369 6367 PROCESS__SETCURRENT, NULL); 6370 - else 6371 - error = -EINVAL; 6368 + break; 6369 + default: 6370 + error = -EOPNOTSUPP; 6371 + break; 6372 + } 6372 6373 if (error) 6373 6374 return error; 6374 6375 ··· 6388 6373 } 6389 6374 error = security_context_to_sid(value, size, 6390 6375 &sid, GFP_KERNEL); 6391 - if (error == -EINVAL && !strcmp(name, "fscreate")) { 6376 + if (error == -EINVAL && attr == LSM_ATTR_FSCREATE) { 6392 6377 if (!has_cap_mac_admin(true)) { 6393 6378 struct audit_buffer *ab; 6394 6379 size_t audit_size; 6395 6380 6396 - /* We strip a nul only if it is at the end, otherwise the 6397 - * context contains a nul and we should audit that */ 6381 + /* We strip a nul only if it is at the end, 6382 + * otherwise the context contains a nul and 6383 + * we should audit that */ 6398 6384 if (str[size - 1] == '\0') 6399 6385 audit_size = size - 1; 6400 6386 else ··· 6406 6390 if (!ab) 6407 6391 return error; 6408 6392 audit_log_format(ab, "op=fscreate invalid_context="); 6409 - audit_log_n_untrustedstring(ab, value, audit_size); 6393 + audit_log_n_untrustedstring(ab, value, 6394 + audit_size); 6410 6395 audit_log_end(ab); 6411 6396 6412 6397 return error; ··· 6430 6413 checks and may_create for the file creation checks. The 6431 6414 operation will then fail if the context is not permitted. */ 6432 6415 tsec = selinux_cred(new); 6433 - if (!strcmp(name, "exec")) { 6416 + if (attr == LSM_ATTR_EXEC) { 6434 6417 tsec->exec_sid = sid; 6435 - } else if (!strcmp(name, "fscreate")) { 6418 + } else if (attr == LSM_ATTR_FSCREATE) { 6436 6419 tsec->create_sid = sid; 6437 - } else if (!strcmp(name, "keycreate")) { 6420 + } else if (attr == LSM_ATTR_KEYCREATE) { 6438 6421 if (sid) { 6439 6422 error = avc_has_perm(mysid, sid, 6440 6423 SECCLASS_KEY, KEY__CREATE, NULL); ··· 6442 6425 goto abort_change; 6443 6426 } 6444 6427 tsec->keycreate_sid = sid; 6445 - } else if (!strcmp(name, "sockcreate")) { 6428 + } else if (attr == LSM_ATTR_SOCKCREATE) { 6446 6429 tsec->sockcreate_sid = sid; 6447 - } else if (!strcmp(name, "current")) { 6430 + } else if (attr == LSM_ATTR_CURRENT) { 6448 6431 error = -EINVAL; 6449 6432 if (sid == 0) 6450 6433 goto abort_change; ··· 6484 6467 abort_change: 6485 6468 abort_creds(new); 6486 6469 return error; 6470 + } 6471 + 6472 + static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx, 6473 + size_t *size, u32 flags) 6474 + { 6475 + char *value; 6476 + size_t total_len; 6477 + int len; 6478 + int rc = 0; 6479 + 6480 + len = selinux_lsm_getattr(attr, current, &value); 6481 + if (len < 0) 6482 + return len; 6483 + 6484 + total_len = ALIGN(struct_size(ctx, ctx, len), 8); 6485 + 6486 + if (total_len > *size) 6487 + rc = -E2BIG; 6488 + else if (ctx) 6489 + rc = lsm_fill_user_ctx(ctx, value, len, LSM_ID_SELINUX, 0); 6490 + 6491 + kfree(value); 6492 + *size = total_len; 6493 + if (rc < 0) 6494 + return rc; 6495 + return 1; 6496 + } 6497 + 6498 + static int selinux_setselfattr(unsigned int attr, struct lsm_ctx *ctx, 6499 + size_t size, u32 flags) 6500 + { 6501 + int rc; 6502 + 6503 + rc = selinux_lsm_setattr(attr, ctx->ctx, ctx->ctx_len); 6504 + if (rc > 0) 6505 + return 0; 6506 + return rc; 6507 + } 6508 + 6509 + static int selinux_getprocattr(struct task_struct *p, 6510 + const char *name, char **value) 6511 + { 6512 + unsigned int attr = lsm_name_to_attr(name); 6513 + int rc; 6514 + 6515 + if (attr) { 6516 + rc = selinux_lsm_getattr(attr, p, value); 6517 + if (rc != -EOPNOTSUPP) 6518 + return rc; 6519 + } 6520 + 6521 + return -EINVAL; 6522 + } 6523 + 6524 + static int selinux_setprocattr(const char *name, void *value, size_t size) 6525 + { 6526 + int attr = lsm_name_to_attr(name); 6527 + 6528 + if (attr) 6529 + return selinux_lsm_setattr(attr, value, size); 6530 + return -EINVAL; 6487 6531 } 6488 6532 6489 6533 static int selinux_ismaclabel(const char *name) ··· 7175 7097 7176 7098 LSM_HOOK_INIT(d_instantiate, selinux_d_instantiate), 7177 7099 7100 + LSM_HOOK_INIT(getselfattr, selinux_getselfattr), 7101 + LSM_HOOK_INIT(setselfattr, selinux_setselfattr), 7178 7102 LSM_HOOK_INIT(getprocattr, selinux_getprocattr), 7179 7103 LSM_HOOK_INIT(setprocattr, selinux_setprocattr), 7180 7104