domain.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. /*
  2. * AppArmor security module
  3. *
  4. * This file contains AppArmor policy attachment and domain transitions
  5. *
  6. * Copyright (C) 2002-2008 Novell/SUSE
  7. * Copyright 2009-2010 Canonical Ltd.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation, version 2 of the
  12. * License.
  13. */
  14. #include <linux/errno.h>
  15. #include <linux/fdtable.h>
  16. #include <linux/file.h>
  17. #include <linux/mount.h>
  18. #include <linux/syscalls.h>
  19. #include <linux/tracehook.h>
  20. #include <linux/personality.h>
  21. #include "include/audit.h"
  22. #include "include/apparmorfs.h"
  23. #include "include/context.h"
  24. #include "include/domain.h"
  25. #include "include/file.h"
  26. #include "include/ipc.h"
  27. #include "include/match.h"
  28. #include "include/path.h"
  29. #include "include/policy.h"
  30. /**
  31. * aa_free_domain_entries - free entries in a domain table
  32. * @domain: the domain table to free (MAYBE NULL)
  33. */
  34. void aa_free_domain_entries(struct aa_domain *domain)
  35. {
  36. int i;
  37. if (domain) {
  38. if (!domain->table)
  39. return;
  40. for (i = 0; i < domain->size; i++)
  41. kzfree(domain->table[i]);
  42. kzfree(domain->table);
  43. domain->table = NULL;
  44. }
  45. }
  46. /**
  47. * may_change_ptraced_domain - check if can change profile on ptraced task
  48. * @task: task we want to change profile of (NOT NULL)
  49. * @to_profile: profile to change to (NOT NULL)
  50. *
  51. * Check if the task is ptraced and if so if the tracing task is allowed
  52. * to trace the new domain
  53. *
  54. * Returns: %0 or error if change not allowed
  55. */
  56. static int may_change_ptraced_domain(struct task_struct *task,
  57. struct aa_profile *to_profile)
  58. {
  59. struct task_struct *tracer;
  60. const struct cred *cred = NULL;
  61. struct aa_profile *tracerp = NULL;
  62. int error = 0;
  63. rcu_read_lock();
  64. tracer = ptrace_parent(task);
  65. if (tracer) {
  66. /* released below */
  67. cred = get_task_cred(tracer);
  68. tracerp = aa_cred_profile(cred);
  69. }
  70. /* not ptraced */
  71. if (!tracer || unconfined(tracerp))
  72. goto out;
  73. error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH);
  74. out:
  75. rcu_read_unlock();
  76. if (cred)
  77. put_cred(cred);
  78. return error;
  79. }
  80. /**
  81. * change_profile_perms - find permissions for change_profile
  82. * @profile: the current profile (NOT NULL)
  83. * @ns: the namespace being switched to (NOT NULL)
  84. * @name: the name of the profile to change to (NOT NULL)
  85. * @request: requested perms
  86. * @start: state to start matching in
  87. *
  88. * Returns: permission set
  89. */
  90. static struct file_perms change_profile_perms(struct aa_profile *profile,
  91. struct aa_namespace *ns,
  92. const char *name, u32 request,
  93. unsigned int start)
  94. {
  95. struct file_perms perms;
  96. struct path_cond cond = { };
  97. unsigned int state;
  98. if (unconfined(profile)) {
  99. perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC;
  100. perms.audit = perms.quiet = perms.kill = 0;
  101. return perms;
  102. } else if (!profile->file.dfa) {
  103. return nullperms;
  104. } else if ((ns == profile->ns)) {
  105. /* try matching against rules with out namespace prepended */
  106. aa_str_perms(profile->file.dfa, start, name, &cond, &perms);
  107. if (COMBINED_PERM_MASK(perms) & request)
  108. return perms;
  109. }
  110. /* try matching with namespace name and then profile */
  111. state = aa_dfa_match(profile->file.dfa, start, ns->base.name);
  112. state = aa_dfa_match_len(profile->file.dfa, state, ":", 1);
  113. aa_str_perms(profile->file.dfa, state, name, &cond, &perms);
  114. return perms;
  115. }
  116. /**
  117. * __attach_match_ - find an attachment match
  118. * @name - to match against (NOT NULL)
  119. * @head - profile list to walk (NOT NULL)
  120. *
  121. * Do a linear search on the profiles in the list. There is a matching
  122. * preference where an exact match is preferred over a name which uses
  123. * expressions to match, and matching expressions with the greatest
  124. * xmatch_len are preferred.
  125. *
  126. * Requires: @head not be shared or have appropriate locks held
  127. *
  128. * Returns: profile or NULL if no match found
  129. */
  130. static struct aa_profile *__attach_match(const char *name,
  131. struct list_head *head)
  132. {
  133. int len = 0;
  134. struct aa_profile *profile, *candidate = NULL;
  135. list_for_each_entry(profile, head, base.list) {
  136. if (profile->flags & PFLAG_NULL)
  137. continue;
  138. if (profile->xmatch && profile->xmatch_len > len) {
  139. unsigned int state = aa_dfa_match(profile->xmatch,
  140. DFA_START, name);
  141. u32 perm = dfa_user_allow(profile->xmatch, state);
  142. /* any accepting state means a valid match. */
  143. if (perm & MAY_EXEC) {
  144. candidate = profile;
  145. len = profile->xmatch_len;
  146. }
  147. } else if (!strcmp(profile->base.name, name))
  148. /* exact non-re match, no more searching required */
  149. return profile;
  150. }
  151. return candidate;
  152. }
  153. /**
  154. * find_attach - do attachment search for unconfined processes
  155. * @ns: the current namespace (NOT NULL)
  156. * @list: list to search (NOT NULL)
  157. * @name: the executable name to match against (NOT NULL)
  158. *
  159. * Returns: profile or NULL if no match found
  160. */
  161. static struct aa_profile *find_attach(struct aa_namespace *ns,
  162. struct list_head *list, const char *name)
  163. {
  164. struct aa_profile *profile;
  165. read_lock(&ns->lock);
  166. profile = aa_get_profile(__attach_match(name, list));
  167. read_unlock(&ns->lock);
  168. return profile;
  169. }
  170. /**
  171. * separate_fqname - separate the namespace and profile names
  172. * @fqname: the fqname name to split (NOT NULL)
  173. * @ns_name: the namespace name if it exists (NOT NULL)
  174. *
  175. * This is the xtable equivalent routine of aa_split_fqname. It finds the
  176. * split in an xtable fqname which contains an embedded \0 instead of a :
  177. * if a namespace is specified. This is done so the xtable is constant and
  178. * isn't re-split on every lookup.
  179. *
  180. * Either the profile or namespace name may be optional but if the namespace
  181. * is specified the profile name termination must be present. This results
  182. * in the following possible encodings:
  183. * profile_name\0
  184. * :ns_name\0profile_name\0
  185. * :ns_name\0\0
  186. *
  187. * NOTE: the xtable fqname is pre-validated at load time in unpack_trans_table
  188. *
  189. * Returns: profile name if it is specified else NULL
  190. */
  191. static const char *separate_fqname(const char *fqname, const char **ns_name)
  192. {
  193. const char *name;
  194. if (fqname[0] == ':') {
  195. /* In this case there is guaranteed to be two \0 terminators
  196. * in the string. They are verified at load time by
  197. * by unpack_trans_table
  198. */
  199. *ns_name = fqname + 1; /* skip : */
  200. name = *ns_name + strlen(*ns_name) + 1;
  201. if (!*name)
  202. name = NULL;
  203. } else {
  204. *ns_name = NULL;
  205. name = fqname;
  206. }
  207. return name;
  208. }
  209. static const char *next_name(int xtype, const char *name)
  210. {
  211. return NULL;
  212. }
  213. /**
  214. * x_table_lookup - lookup an x transition name via transition table
  215. * @profile: current profile (NOT NULL)
  216. * @xindex: index into x transition table
  217. *
  218. * Returns: refcounted profile, or NULL on failure (MAYBE NULL)
  219. */
  220. static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
  221. {
  222. struct aa_profile *new_profile = NULL;
  223. struct aa_namespace *ns = profile->ns;
  224. u32 xtype = xindex & AA_X_TYPE_MASK;
  225. int index = xindex & AA_X_INDEX_MASK;
  226. const char *name;
  227. /* index is guaranteed to be in range, validated at load time */
  228. for (name = profile->file.trans.table[index]; !new_profile && name;
  229. name = next_name(xtype, name)) {
  230. struct aa_namespace *new_ns;
  231. const char *xname = NULL;
  232. new_ns = NULL;
  233. if (xindex & AA_X_CHILD) {
  234. /* release by caller */
  235. new_profile = aa_find_child(profile, name);
  236. continue;
  237. } else if (*name == ':') {
  238. /* switching namespace */
  239. const char *ns_name;
  240. xname = name = separate_fqname(name, &ns_name);
  241. if (!xname)
  242. /* no name so use profile name */
  243. xname = profile->base.hname;
  244. if (*ns_name == '@') {
  245. /* TODO: variable support */
  246. ;
  247. }
  248. /* released below */
  249. new_ns = aa_find_namespace(ns, ns_name);
  250. if (!new_ns)
  251. continue;
  252. } else if (*name == '@') {
  253. /* TODO: variable support */
  254. continue;
  255. } else {
  256. /* basic namespace lookup */
  257. xname = name;
  258. }
  259. /* released by caller */
  260. new_profile = aa_lookup_profile(new_ns ? new_ns : ns, xname);
  261. aa_put_namespace(new_ns);
  262. }
  263. /* released by caller */
  264. return new_profile;
  265. }
  266. /**
  267. * x_to_profile - get target profile for a given xindex
  268. * @profile: current profile (NOT NULL)
  269. * @name: name to lookup (NOT NULL)
  270. * @xindex: index into x transition table
  271. *
  272. * find profile for a transition index
  273. *
  274. * Returns: refcounted profile or NULL if not found available
  275. */
  276. static struct aa_profile *x_to_profile(struct aa_profile *profile,
  277. const char *name, u32 xindex)
  278. {
  279. struct aa_profile *new_profile = NULL;
  280. struct aa_namespace *ns = profile->ns;
  281. u32 xtype = xindex & AA_X_TYPE_MASK;
  282. switch (xtype) {
  283. case AA_X_NONE:
  284. /* fail exec unless ix || ux fallback - handled by caller */
  285. return NULL;
  286. case AA_X_NAME:
  287. if (xindex & AA_X_CHILD)
  288. /* released by caller */
  289. new_profile = find_attach(ns, &profile->base.profiles,
  290. name);
  291. else
  292. /* released by caller */
  293. new_profile = find_attach(ns, &ns->base.profiles,
  294. name);
  295. break;
  296. case AA_X_TABLE:
  297. /* released by caller */
  298. new_profile = x_table_lookup(profile, xindex);
  299. break;
  300. }
  301. /* released by caller */
  302. return new_profile;
  303. }
  304. /**
  305. * apparmor_bprm_set_creds - set the new creds on the bprm struct
  306. * @bprm: binprm for the exec (NOT NULL)
  307. *
  308. * Returns: %0 or error on failure
  309. */
  310. int apparmor_bprm_set_creds(struct linux_binprm *bprm)
  311. {
  312. struct aa_task_cxt *cxt;
  313. struct aa_profile *profile, *new_profile = NULL;
  314. struct aa_namespace *ns;
  315. char *buffer = NULL;
  316. unsigned int state;
  317. struct file_perms perms = {};
  318. struct path_cond cond = {
  319. bprm->file->f_path.dentry->d_inode->i_uid,
  320. bprm->file->f_path.dentry->d_inode->i_mode
  321. };
  322. const char *name = NULL, *target = NULL, *info = NULL;
  323. int error = cap_bprm_set_creds(bprm);
  324. if (error)
  325. return error;
  326. if (bprm->cred_prepared)
  327. return 0;
  328. /* XXX: no_new_privs is not usable with AppArmor yet */
  329. if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
  330. return -EPERM;
  331. cxt = bprm->cred->security;
  332. BUG_ON(!cxt);
  333. profile = aa_get_profile(aa_newest_version(cxt->profile));
  334. /*
  335. * get the namespace from the replacement profile as replacement
  336. * can change the namespace
  337. */
  338. ns = profile->ns;
  339. state = profile->file.start;
  340. /* buffer freed below, name is pointer into buffer */
  341. error = aa_path_name(&bprm->file->f_path, profile->path_flags, &buffer,
  342. &name, &info);
  343. if (error) {
  344. if (profile->flags &
  345. (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED))
  346. error = 0;
  347. name = bprm->filename;
  348. goto audit;
  349. }
  350. /* Test for onexec first as onexec directives override other
  351. * x transitions.
  352. */
  353. if (unconfined(profile)) {
  354. /* unconfined task */
  355. if (cxt->onexec)
  356. /* change_profile on exec already been granted */
  357. new_profile = aa_get_profile(cxt->onexec);
  358. else
  359. new_profile = find_attach(ns, &ns->base.profiles, name);
  360. if (!new_profile)
  361. goto cleanup;
  362. /*
  363. * NOTE: Domain transitions from unconfined are allowed
  364. * even when no_new_privs is set because this aways results
  365. * in a further reduction of permissions.
  366. */
  367. goto apply;
  368. }
  369. /* find exec permissions for name */
  370. state = aa_str_perms(profile->file.dfa, state, name, &cond, &perms);
  371. if (cxt->onexec) {
  372. struct file_perms cp;
  373. info = "change_profile onexec";
  374. if (!(perms.allow & AA_MAY_ONEXEC))
  375. goto audit;
  376. /* test if this exec can be paired with change_profile onexec.
  377. * onexec permission is linked to exec with a standard pairing
  378. * exec\0change_profile
  379. */
  380. state = aa_dfa_null_transition(profile->file.dfa, state);
  381. cp = change_profile_perms(profile, cxt->onexec->ns,
  382. cxt->onexec->base.name,
  383. AA_MAY_ONEXEC, state);
  384. if (!(cp.allow & AA_MAY_ONEXEC))
  385. goto audit;
  386. new_profile = aa_get_profile(aa_newest_version(cxt->onexec));
  387. goto apply;
  388. }
  389. if (perms.allow & MAY_EXEC) {
  390. /* exec permission determine how to transition */
  391. new_profile = x_to_profile(profile, name, perms.xindex);
  392. if (!new_profile) {
  393. if (perms.xindex & AA_X_INHERIT) {
  394. /* (p|c|n)ix - don't change profile but do
  395. * use the newest version, which was picked
  396. * up above when getting profile
  397. */
  398. info = "ix fallback";
  399. new_profile = aa_get_profile(profile);
  400. goto x_clear;
  401. } else if (perms.xindex & AA_X_UNCONFINED) {
  402. new_profile = aa_get_profile(ns->unconfined);
  403. info = "ux fallback";
  404. } else {
  405. error = -ENOENT;
  406. info = "profile not found";
  407. }
  408. }
  409. } else if (COMPLAIN_MODE(profile)) {
  410. /* no exec permission - are we in learning mode */
  411. new_profile = aa_new_null_profile(profile, 0);
  412. if (!new_profile) {
  413. error = -ENOMEM;
  414. info = "could not create null profile";
  415. } else {
  416. error = -EACCES;
  417. target = new_profile->base.hname;
  418. }
  419. perms.xindex |= AA_X_UNSAFE;
  420. } else
  421. /* fail exec */
  422. error = -EACCES;
  423. /*
  424. * Policy has specified a domain transition, if no_new_privs then
  425. * fail the exec.
  426. */
  427. if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) {
  428. aa_put_profile(new_profile);
  429. error = -EPERM;
  430. goto cleanup;
  431. }
  432. if (!new_profile)
  433. goto audit;
  434. if (bprm->unsafe & LSM_UNSAFE_SHARE) {
  435. /* FIXME: currently don't mediate shared state */
  436. ;
  437. }
  438. if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
  439. error = may_change_ptraced_domain(current, new_profile);
  440. if (error) {
  441. aa_put_profile(new_profile);
  442. goto audit;
  443. }
  444. }
  445. /* Determine if secure exec is needed.
  446. * Can be at this point for the following reasons:
  447. * 1. unconfined switching to confined
  448. * 2. confined switching to different confinement
  449. * 3. confined switching to unconfined
  450. *
  451. * Cases 2 and 3 are marked as requiring secure exec
  452. * (unless policy specified "unsafe exec")
  453. *
  454. * bprm->unsafe is used to cache the AA_X_UNSAFE permission
  455. * to avoid having to recompute in secureexec
  456. */
  457. if (!(perms.xindex & AA_X_UNSAFE)) {
  458. AA_DEBUG("scrubbing environment variables for %s profile=%s\n",
  459. name, new_profile->base.hname);
  460. bprm->unsafe |= AA_SECURE_X_NEEDED;
  461. }
  462. apply:
  463. target = new_profile->base.hname;
  464. /* when transitioning profiles clear unsafe personality bits */
  465. bprm->per_clear |= PER_CLEAR_ON_SETID;
  466. x_clear:
  467. aa_put_profile(cxt->profile);
  468. /* transfer new profile reference will be released when cxt is freed */
  469. cxt->profile = new_profile;
  470. /* clear out all temporary/transitional state from the context */
  471. aa_put_profile(cxt->previous);
  472. aa_put_profile(cxt->onexec);
  473. cxt->previous = NULL;
  474. cxt->onexec = NULL;
  475. cxt->token = 0;
  476. audit:
  477. error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC,
  478. name, target, cond.uid, info, error);
  479. cleanup:
  480. aa_put_profile(profile);
  481. kfree(buffer);
  482. return error;
  483. }
  484. /**
  485. * apparmor_bprm_secureexec - determine if secureexec is needed
  486. * @bprm: binprm for exec (NOT NULL)
  487. *
  488. * Returns: %1 if secureexec is needed else %0
  489. */
  490. int apparmor_bprm_secureexec(struct linux_binprm *bprm)
  491. {
  492. int ret = cap_bprm_secureexec(bprm);
  493. /* the decision to use secure exec is computed in set_creds
  494. * and stored in bprm->unsafe.
  495. */
  496. if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
  497. ret = 1;
  498. return ret;
  499. }
  500. /**
  501. * apparmor_bprm_committing_creds - do task cleanup on committing new creds
  502. * @bprm: binprm for the exec (NOT NULL)
  503. */
  504. void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
  505. {
  506. struct aa_profile *profile = __aa_current_profile();
  507. struct aa_task_cxt *new_cxt = bprm->cred->security;
  508. /* bail out if unconfined or not changing profile */
  509. if ((new_cxt->profile == profile) ||
  510. (unconfined(new_cxt->profile)))
  511. return;
  512. current->pdeath_signal = 0;
  513. /* reset soft limits and set hard limits for the new profile */
  514. __aa_transition_rlimits(profile, new_cxt->profile);
  515. }
  516. /**
  517. * apparmor_bprm_commited_cred - do cleanup after new creds committed
  518. * @bprm: binprm for the exec (NOT NULL)
  519. */
  520. void apparmor_bprm_committed_creds(struct linux_binprm *bprm)
  521. {
  522. /* TODO: cleanup signals - ipc mediation */
  523. return;
  524. }
  525. /*
  526. * Functions for self directed profile change
  527. */
  528. /**
  529. * new_compound_name - create an hname with @n2 appended to @n1
  530. * @n1: base of hname (NOT NULL)
  531. * @n2: name to append (NOT NULL)
  532. *
  533. * Returns: new name or NULL on error
  534. */
  535. static char *new_compound_name(const char *n1, const char *n2)
  536. {
  537. char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
  538. if (name)
  539. sprintf(name, "%s//%s", n1, n2);
  540. return name;
  541. }
  542. /**
  543. * aa_change_hat - change hat to/from subprofile
  544. * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0)
  545. * @count: number of hat names in @hats
  546. * @token: magic value to validate the hat change
  547. * @permtest: true if this is just a permission test
  548. *
  549. * Change to the first profile specified in @hats that exists, and store
  550. * the @hat_magic in the current task context. If the count == 0 and the
  551. * @token matches that stored in the current task context, return to the
  552. * top level profile.
  553. *
  554. * Returns %0 on success, error otherwise.
  555. */
  556. int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
  557. {
  558. const struct cred *cred;
  559. struct aa_task_cxt *cxt;
  560. struct aa_profile *profile, *previous_profile, *hat = NULL;
  561. char *name = NULL;
  562. int i;
  563. struct file_perms perms = {};
  564. const char *target = NULL, *info = NULL;
  565. int error = 0;
  566. /*
  567. * Fail explicitly requested domain transitions if no_new_privs.
  568. * There is no exception for unconfined as change_hat is not
  569. * available.
  570. */
  571. if (task_no_new_privs(current))
  572. return -EPERM;
  573. /* released below */
  574. cred = get_current_cred();
  575. cxt = cred->security;
  576. profile = aa_cred_profile(cred);
  577. previous_profile = cxt->previous;
  578. if (unconfined(profile)) {
  579. info = "unconfined";
  580. error = -EPERM;
  581. goto audit;
  582. }
  583. if (count) {
  584. /* attempting to change into a new hat or switch to a sibling */
  585. struct aa_profile *root;
  586. root = PROFILE_IS_HAT(profile) ? profile->parent : profile;
  587. /* find first matching hat */
  588. for (i = 0; i < count && !hat; i++)
  589. /* released below */
  590. hat = aa_find_child(root, hats[i]);
  591. if (!hat) {
  592. if (!COMPLAIN_MODE(root) || permtest) {
  593. if (list_empty(&root->base.profiles))
  594. error = -ECHILD;
  595. else
  596. error = -ENOENT;
  597. goto out;
  598. }
  599. /*
  600. * In complain mode and failed to match any hats.
  601. * Audit the failure is based off of the first hat
  602. * supplied. This is done due how userspace
  603. * interacts with change_hat.
  604. *
  605. * TODO: Add logging of all failed hats
  606. */
  607. /* freed below */
  608. name = new_compound_name(root->base.hname, hats[0]);
  609. target = name;
  610. /* released below */
  611. hat = aa_new_null_profile(profile, 1);
  612. if (!hat) {
  613. info = "failed null profile create";
  614. error = -ENOMEM;
  615. goto audit;
  616. }
  617. } else {
  618. target = hat->base.hname;
  619. if (!PROFILE_IS_HAT(hat)) {
  620. info = "target not hat";
  621. error = -EPERM;
  622. goto audit;
  623. }
  624. }
  625. error = may_change_ptraced_domain(current, hat);
  626. if (error) {
  627. info = "ptraced";
  628. error = -EPERM;
  629. goto audit;
  630. }
  631. if (!permtest) {
  632. error = aa_set_current_hat(hat, token);
  633. if (error == -EACCES)
  634. /* kill task in case of brute force attacks */
  635. perms.kill = AA_MAY_CHANGEHAT;
  636. else if (name && !error)
  637. /* reset error for learning of new hats */
  638. error = -ENOENT;
  639. }
  640. } else if (previous_profile) {
  641. /* Return to saved profile. Kill task if restore fails
  642. * to avoid brute force attacks
  643. */
  644. target = previous_profile->base.hname;
  645. error = aa_restore_previous_profile(token);
  646. perms.kill = AA_MAY_CHANGEHAT;
  647. } else
  648. /* ignore restores when there is no saved profile */
  649. goto out;
  650. audit:
  651. if (!permtest)
  652. error = aa_audit_file(profile, &perms, GFP_KERNEL,
  653. OP_CHANGE_HAT, AA_MAY_CHANGEHAT, NULL,
  654. target, 0, info, error);
  655. out:
  656. aa_put_profile(hat);
  657. kfree(name);
  658. put_cred(cred);
  659. return error;
  660. }
  661. /**
  662. * aa_change_profile - perform a one-way profile transition
  663. * @ns_name: name of the profile namespace to change to (MAYBE NULL)
  664. * @hname: name of profile to change to (MAYBE NULL)
  665. * @onexec: whether this transition is to take place immediately or at exec
  666. * @permtest: true if this is just a permission test
  667. *
  668. * Change to new profile @name. Unlike with hats, there is no way
  669. * to change back. If @name isn't specified the current profile name is
  670. * used.
  671. * If @onexec then the transition is delayed until
  672. * the next exec.
  673. *
  674. * Returns %0 on success, error otherwise.
  675. */
  676. int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
  677. bool permtest)
  678. {
  679. const struct cred *cred;
  680. struct aa_task_cxt *cxt;
  681. struct aa_profile *profile, *target = NULL;
  682. struct aa_namespace *ns = NULL;
  683. struct file_perms perms = {};
  684. const char *name = NULL, *info = NULL;
  685. int op, error = 0;
  686. u32 request;
  687. if (!hname && !ns_name)
  688. return -EINVAL;
  689. if (onexec) {
  690. request = AA_MAY_ONEXEC;
  691. op = OP_CHANGE_ONEXEC;
  692. } else {
  693. request = AA_MAY_CHANGE_PROFILE;
  694. op = OP_CHANGE_PROFILE;
  695. }
  696. cred = get_current_cred();
  697. cxt = cred->security;
  698. profile = aa_cred_profile(cred);
  699. /*
  700. * Fail explicitly requested domain transitions if no_new_privs
  701. * and not unconfined.
  702. * Domain transitions from unconfined are allowed even when
  703. * no_new_privs is set because this aways results in a reduction
  704. * of permissions.
  705. */
  706. if (task_no_new_privs(current) && !unconfined(profile)) {
  707. put_cred(cred);
  708. return -EPERM;
  709. }
  710. if (ns_name) {
  711. /* released below */
  712. ns = aa_find_namespace(profile->ns, ns_name);
  713. if (!ns) {
  714. /* we don't create new namespace in complain mode */
  715. name = ns_name;
  716. info = "namespace not found";
  717. error = -ENOENT;
  718. goto audit;
  719. }
  720. } else
  721. /* released below */
  722. ns = aa_get_namespace(profile->ns);
  723. /* if the name was not specified, use the name of the current profile */
  724. if (!hname) {
  725. if (unconfined(profile))
  726. hname = ns->unconfined->base.hname;
  727. else
  728. hname = profile->base.hname;
  729. }
  730. perms = change_profile_perms(profile, ns, hname, request,
  731. profile->file.start);
  732. if (!(perms.allow & request)) {
  733. error = -EACCES;
  734. goto audit;
  735. }
  736. /* released below */
  737. target = aa_lookup_profile(ns, hname);
  738. if (!target) {
  739. info = "profile not found";
  740. error = -ENOENT;
  741. if (permtest || !COMPLAIN_MODE(profile))
  742. goto audit;
  743. /* released below */
  744. target = aa_new_null_profile(profile, 0);
  745. if (!target) {
  746. info = "failed null profile create";
  747. error = -ENOMEM;
  748. goto audit;
  749. }
  750. }
  751. /* check if tracing task is allowed to trace target domain */
  752. error = may_change_ptraced_domain(current, target);
  753. if (error) {
  754. info = "ptrace prevents transition";
  755. goto audit;
  756. }
  757. if (permtest)
  758. goto audit;
  759. if (onexec)
  760. error = aa_set_current_onexec(target);
  761. else
  762. error = aa_replace_current_profile(target);
  763. audit:
  764. if (!permtest)
  765. error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request,
  766. name, hname, 0, info, error);
  767. aa_put_namespace(ns);
  768. aa_put_profile(target);
  769. put_cred(cred);
  770. return error;
  771. }