domain.c 22 KB

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