domain.c 22 KB

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