domain.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * AppArmor security module
  4. *
  5. * This file contains AppArmor policy attachment and domain transitions
  6. *
  7. * Copyright (C) 2002-2008 Novell/SUSE
  8. * Copyright 2009-2010 Canonical Ltd.
  9. */
  10. #include <linux/errno.h>
  11. #include <linux/fs.h>
  12. #include <linux/file.h>
  13. #include <linux/mount.h>
  14. #include <linux/syscalls.h>
  15. #include <linux/personality.h>
  16. #include <linux/xattr.h>
  17. #include <linux/user_namespace.h>
  18. #include "include/audit.h"
  19. #include "include/apparmorfs.h"
  20. #include "include/cred.h"
  21. #include "include/domain.h"
  22. #include "include/file.h"
  23. #include "include/ipc.h"
  24. #include "include/match.h"
  25. #include "include/path.h"
  26. #include "include/policy.h"
  27. #include "include/policy_ns.h"
  28. static const char * const CONFLICTING_ATTACH_STR = "conflicting profile attachments";
  29. static const char * const CONFLICTING_ATTACH_STR_IX =
  30. "conflicting profile attachments - ix fallback";
  31. static const char * const CONFLICTING_ATTACH_STR_UX =
  32. "conflicting profile attachments - ux fallback";
  33. /**
  34. * may_change_ptraced_domain - check if can change profile on ptraced task
  35. * @to_cred: cred of task changing domain
  36. * @to_label: profile to change to (NOT NULL)
  37. * @info: message if there is an error
  38. *
  39. * Check if current is ptraced and if so if the tracing task is allowed
  40. * to trace the new domain
  41. *
  42. * Returns: %0 or error if change not allowed
  43. */
  44. static int may_change_ptraced_domain(const struct cred *to_cred,
  45. struct aa_label *to_label,
  46. const char **info)
  47. {
  48. struct task_struct *tracer;
  49. struct aa_label *tracerl = NULL;
  50. const struct cred *tracer_cred = NULL;
  51. int error = 0;
  52. rcu_read_lock();
  53. tracer = ptrace_parent(current);
  54. if (tracer) {
  55. /* released below */
  56. tracerl = aa_get_task_label(tracer);
  57. tracer_cred = get_task_cred(tracer);
  58. }
  59. /* not ptraced */
  60. if (!tracer || unconfined(tracerl))
  61. goto out;
  62. error = aa_may_ptrace(tracer_cred, tracerl, to_cred, to_label,
  63. PTRACE_MODE_ATTACH);
  64. out:
  65. rcu_read_unlock();
  66. aa_put_label(tracerl);
  67. put_cred(tracer_cred);
  68. if (error)
  69. *info = "ptrace prevents transition";
  70. return error;
  71. }
  72. /**** TODO: dedup to aa_label_match - needs perm and dfa, merging
  73. * specifically this is an exact copy of aa_label_match except
  74. * aa_compute_perms is replaced with aa_compute_fperms
  75. * and policy->dfa with file->dfa
  76. ****/
  77. /* match a profile and its associated ns component if needed
  78. * Assumes visibility test has already been done.
  79. * If a subns profile is not to be matched should be prescreened with
  80. * visibility test.
  81. */
  82. static inline aa_state_t match_component(struct aa_profile *profile,
  83. struct aa_profile *tp,
  84. bool stack, aa_state_t state)
  85. {
  86. struct aa_ruleset *rules = profile->label.rules[0];
  87. const char *ns_name;
  88. if (stack)
  89. state = aa_dfa_match(rules->file->dfa, state, "&");
  90. if (profile->ns == tp->ns)
  91. return aa_dfa_match(rules->file->dfa, state, tp->base.hname);
  92. /* try matching with namespace name and then profile */
  93. ns_name = aa_ns_name(profile->ns, tp->ns, true);
  94. state = aa_dfa_match_len(rules->file->dfa, state, ":", 1);
  95. state = aa_dfa_match(rules->file->dfa, state, ns_name);
  96. state = aa_dfa_match_len(rules->file->dfa, state, ":", 1);
  97. return aa_dfa_match(rules->file->dfa, state, tp->base.hname);
  98. }
  99. /**
  100. * label_compound_match - find perms for full compound label
  101. * @profile: profile to find perms for
  102. * @label: label to check access permissions for
  103. * @stack: whether this is a stacking request
  104. * @state: state to start match in
  105. * @inview: whether to match labels in view or only in scope
  106. * @request: permissions to request
  107. * @perms: perms struct to set
  108. *
  109. * Returns: 0 on success else ERROR
  110. *
  111. * For the label A//&B//&C this does the perm match for A//&B//&C
  112. * @perms should be preinitialized with allperms OR a previous permission
  113. * check to be stacked.
  114. */
  115. static int label_compound_match(struct aa_profile *profile,
  116. struct aa_label *label, bool stack,
  117. aa_state_t state, bool inview, u32 request,
  118. struct aa_perms *perms)
  119. {
  120. struct aa_ruleset *rules = profile->label.rules[0];
  121. struct aa_profile *tp;
  122. struct label_it i;
  123. struct path_cond cond = { };
  124. /* find first subcomponent that is in view and going to be interated with */
  125. label_for_each(i, label, tp) {
  126. if (!aa_ns_visible(profile->ns, tp->ns, inview))
  127. continue;
  128. state = match_component(profile, tp, stack, state);
  129. if (!state)
  130. goto fail;
  131. goto next;
  132. }
  133. /* no component visible */
  134. *perms = allperms;
  135. return 0;
  136. next:
  137. label_for_each_cont(i, label, tp) {
  138. if (!aa_ns_visible(profile->ns, tp->ns, inview))
  139. continue;
  140. state = aa_dfa_match(rules->file->dfa, state, "//&");
  141. state = match_component(profile, tp, false, state);
  142. if (!state)
  143. goto fail;
  144. }
  145. *perms = *(aa_lookup_condperms(current_fsuid(), rules->file, state,
  146. &cond));
  147. aa_apply_modes_to_perms(profile, perms);
  148. if ((perms->allow & request) != request)
  149. return -EACCES;
  150. return 0;
  151. fail:
  152. *perms = nullperms;
  153. return -EACCES;
  154. }
  155. /**
  156. * label_components_match - find perms for all subcomponents of a label
  157. * @profile: profile to find perms for
  158. * @label: label to check access permissions for
  159. * @stack: whether this is a stacking request
  160. * @start: state to start match in
  161. * @inview: whether to match labels in view or only in scope
  162. * @request: permissions to request
  163. * @perms: an initialized perms struct to add accumulation to
  164. *
  165. * Returns: 0 on success else ERROR
  166. *
  167. * For the label A//&B//&C this does the perm match for each of A and B and C
  168. * @perms should be preinitialized with allperms OR a previous permission
  169. * check to be stacked.
  170. */
  171. static int label_components_match(struct aa_profile *profile,
  172. struct aa_label *label, bool stack,
  173. aa_state_t start, bool inview, u32 request,
  174. struct aa_perms *perms)
  175. {
  176. struct aa_ruleset *rules = profile->label.rules[0];
  177. struct aa_profile *tp;
  178. struct label_it i;
  179. struct aa_perms tmp;
  180. struct path_cond cond = { };
  181. aa_state_t state = 0;
  182. /* find first subcomponent to test */
  183. label_for_each(i, label, tp) {
  184. if (!aa_ns_visible(profile->ns, tp->ns, inview))
  185. continue;
  186. state = match_component(profile, tp, stack, start);
  187. if (!state)
  188. goto fail;
  189. goto next;
  190. }
  191. /* no subcomponents visible - no change in perms */
  192. return 0;
  193. next:
  194. tmp = *(aa_lookup_condperms(current_fsuid(), rules->file, state,
  195. &cond));
  196. aa_apply_modes_to_perms(profile, &tmp);
  197. aa_perms_accum(perms, &tmp);
  198. label_for_each_cont(i, label, tp) {
  199. if (!aa_ns_visible(profile->ns, tp->ns, inview))
  200. continue;
  201. state = match_component(profile, tp, stack, start);
  202. if (!state)
  203. goto fail;
  204. tmp = *(aa_lookup_condperms(current_fsuid(), rules->file, state,
  205. &cond));
  206. aa_apply_modes_to_perms(profile, &tmp);
  207. aa_perms_accum(perms, &tmp);
  208. }
  209. if ((perms->allow & request) != request)
  210. return -EACCES;
  211. return 0;
  212. fail:
  213. *perms = nullperms;
  214. return -EACCES;
  215. }
  216. /**
  217. * label_match - do a multi-component label match
  218. * @profile: profile to match against (NOT NULL)
  219. * @label: label to match (NOT NULL)
  220. * @stack: whether this is a stacking request
  221. * @state: state to start in
  222. * @inview: whether to match labels in view or only in scope
  223. * @request: permission request
  224. * @perms: Returns computed perms (NOT NULL)
  225. *
  226. * Returns: the state the match finished in, may be the none matching state
  227. */
  228. static int label_match(struct aa_profile *profile, struct aa_label *label,
  229. bool stack, aa_state_t state, bool inview, u32 request,
  230. struct aa_perms *perms)
  231. {
  232. int error;
  233. *perms = nullperms;
  234. error = label_compound_match(profile, label, stack, state, inview,
  235. request, perms);
  236. if (!error)
  237. return error;
  238. *perms = allperms;
  239. return label_components_match(profile, label, stack, state, inview,
  240. request, perms);
  241. }
  242. /******* end TODO: dedup *****/
  243. /**
  244. * change_profile_perms - find permissions for change_profile
  245. * @profile: the current profile (NOT NULL)
  246. * @target: label to transition to (NOT NULL)
  247. * @stack: whether this is a stacking request
  248. * @request: requested perms
  249. * @start: state to start matching in
  250. * @perms: Returns computed perms (NOT NULL)
  251. *
  252. *
  253. * Returns: permission set
  254. *
  255. * currently only matches full label A//&B//&C or individual components A, B, C
  256. * not arbitrary combinations. Eg. A//&B, C
  257. */
  258. static int change_profile_perms(struct aa_profile *profile,
  259. struct aa_label *target, bool stack,
  260. u32 request, aa_state_t start,
  261. struct aa_perms *perms)
  262. {
  263. if (profile_unconfined(profile)) {
  264. perms->allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC;
  265. perms->audit = perms->quiet = perms->kill = 0;
  266. return 0;
  267. }
  268. /* TODO: add profile in ns screening */
  269. return label_match(profile, target, stack, start, true, request, perms);
  270. }
  271. /**
  272. * aa_xattrs_match - check whether a file matches the xattrs defined in profile
  273. * @bprm: binprm struct for the process to validate
  274. * @profile: profile to match against (NOT NULL)
  275. * @state: state to start match in
  276. *
  277. * Returns: number of extended attributes that matched, or < 0 on error
  278. */
  279. static int aa_xattrs_match(const struct linux_binprm *bprm,
  280. struct aa_profile *profile, aa_state_t state)
  281. {
  282. int i;
  283. struct dentry *d;
  284. char *value = NULL;
  285. struct aa_attachment *attach = &profile->attach;
  286. int size, value_size = 0, ret = attach->xattr_count;
  287. if (!bprm || !attach->xattr_count)
  288. return 0;
  289. might_sleep();
  290. /* transition from exec match to xattr set */
  291. state = aa_dfa_outofband_transition(attach->xmatch->dfa, state);
  292. d = bprm->file->f_path.dentry;
  293. for (i = 0; i < attach->xattr_count; i++) {
  294. size = vfs_getxattr_alloc(&nop_mnt_idmap, d, attach->xattrs[i],
  295. &value, value_size, GFP_KERNEL);
  296. if (size >= 0) {
  297. struct aa_perms *perms;
  298. /*
  299. * Check the xattr presence before value. This ensure
  300. * that not present xattr can be distinguished from a 0
  301. * length value or rule that matches any value
  302. */
  303. state = aa_dfa_null_transition(attach->xmatch->dfa,
  304. state);
  305. /* Check xattr value */
  306. state = aa_dfa_match_len(attach->xmatch->dfa, state,
  307. value, size);
  308. perms = aa_lookup_perms(attach->xmatch, state);
  309. if (!(perms->allow & MAY_EXEC)) {
  310. ret = -EINVAL;
  311. goto out;
  312. }
  313. }
  314. /* transition to next element */
  315. state = aa_dfa_outofband_transition(attach->xmatch->dfa, state);
  316. if (size < 0) {
  317. /*
  318. * No xattr match, so verify if transition to
  319. * next element was valid. IFF so the xattr
  320. * was optional.
  321. */
  322. if (!state) {
  323. ret = -EINVAL;
  324. goto out;
  325. }
  326. /* don't count missing optional xattr as matched */
  327. ret--;
  328. }
  329. }
  330. out:
  331. kfree(value);
  332. return ret;
  333. }
  334. /**
  335. * find_attach - do attachment search for unconfined processes
  336. * @bprm: binprm structure of transitioning task
  337. * @ns: the current namespace (NOT NULL)
  338. * @head: profile list to walk (NOT NULL)
  339. * @name: to match against (NOT NULL)
  340. * @info: info message if there was an error (NOT NULL)
  341. *
  342. * Do a linear search on the profiles in the list. There is a matching
  343. * preference where an exact match is preferred over a name which uses
  344. * expressions to match, and matching expressions with the greatest
  345. * xmatch_len are preferred.
  346. *
  347. * Requires: @head not be shared or have appropriate locks held
  348. *
  349. * Returns: label or NULL if no match found
  350. */
  351. static struct aa_label *find_attach(const struct linux_binprm *bprm,
  352. struct aa_ns *ns, struct list_head *head,
  353. const char *name, const char **info)
  354. {
  355. int candidate_len = 0, candidate_xattrs = 0;
  356. bool conflict = false;
  357. struct aa_profile *profile, *candidate = NULL;
  358. AA_BUG(!name);
  359. AA_BUG(!head);
  360. rcu_read_lock();
  361. restart:
  362. list_for_each_entry_rcu(profile, head, base.list) {
  363. struct aa_attachment *attach = &profile->attach;
  364. if (profile->label.flags & FLAG_NULL &&
  365. &profile->label == ns_unconfined(profile->ns))
  366. continue;
  367. /* Find the "best" matching profile. Profiles must
  368. * match the path and extended attributes (if any)
  369. * associated with the file. A more specific path
  370. * match will be preferred over a less specific one,
  371. * and a match with more matching extended attributes
  372. * will be preferred over one with fewer. If the best
  373. * match has both the same level of path specificity
  374. * and the same number of matching extended attributes
  375. * as another profile, signal a conflict and refuse to
  376. * match.
  377. */
  378. if (attach->xmatch->dfa) {
  379. unsigned int count;
  380. aa_state_t state;
  381. struct aa_perms *perms;
  382. state = aa_dfa_leftmatch(attach->xmatch->dfa,
  383. attach->xmatch->start[AA_CLASS_XMATCH],
  384. name, &count);
  385. perms = aa_lookup_perms(attach->xmatch, state);
  386. /* any accepting state means a valid match. */
  387. if (perms->allow & MAY_EXEC) {
  388. int ret = 0;
  389. if (count < candidate_len)
  390. continue;
  391. if (bprm && attach->xattr_count) {
  392. long rev = READ_ONCE(ns->revision);
  393. if (!aa_get_profile_not0(profile))
  394. goto restart;
  395. rcu_read_unlock();
  396. ret = aa_xattrs_match(bprm, profile,
  397. state);
  398. rcu_read_lock();
  399. aa_put_profile(profile);
  400. if (rev !=
  401. READ_ONCE(ns->revision))
  402. /* policy changed */
  403. goto restart;
  404. /*
  405. * Fail matching if the xattrs don't
  406. * match
  407. */
  408. if (ret < 0)
  409. continue;
  410. }
  411. /*
  412. * TODO: allow for more flexible best match
  413. *
  414. * The new match isn't more specific
  415. * than the current best match
  416. */
  417. if (count == candidate_len &&
  418. ret <= candidate_xattrs) {
  419. /* Match is equivalent, so conflict */
  420. if (ret == candidate_xattrs)
  421. conflict = true;
  422. continue;
  423. }
  424. /* Either the same length with more matching
  425. * xattrs, or a longer match
  426. */
  427. candidate = profile;
  428. candidate_len = max(count, attach->xmatch_len);
  429. candidate_xattrs = ret;
  430. conflict = false;
  431. }
  432. } else if (!strcmp(profile->base.name, name)) {
  433. /*
  434. * old exact non-re match, without conditionals such
  435. * as xattrs. no more searching required
  436. */
  437. candidate = profile;
  438. goto out;
  439. }
  440. }
  441. if (!candidate || conflict) {
  442. if (conflict)
  443. *info = CONFLICTING_ATTACH_STR;
  444. rcu_read_unlock();
  445. return NULL;
  446. }
  447. out:
  448. candidate = aa_get_newest_profile(candidate);
  449. rcu_read_unlock();
  450. return &candidate->label;
  451. }
  452. static const char *next_name(int xtype, const char *name)
  453. {
  454. return NULL;
  455. }
  456. /**
  457. * x_table_lookup - lookup an x transition name via transition table
  458. * @profile: current profile (NOT NULL)
  459. * @xindex: index into x transition table
  460. * @name: returns: name tested to find label (NOT NULL)
  461. *
  462. * Returns: refcounted label, or NULL on failure (MAYBE NULL)
  463. * @name will always be set with the last name tried
  464. */
  465. struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
  466. const char **name)
  467. {
  468. struct aa_ruleset *rules = profile->label.rules[0];
  469. struct aa_label *label = NULL;
  470. u32 xtype = xindex & AA_X_TYPE_MASK;
  471. int index = xindex & AA_X_INDEX_MASK;
  472. const char *next;
  473. AA_BUG(!name);
  474. /* index is guaranteed to be in range, validated at load time */
  475. /* TODO: move lookup parsing to unpack time so this is a straight
  476. * index into the resultant label
  477. */
  478. for (next = rules->file->trans.table[index].strs; next;
  479. next = next_name(xtype, next)) {
  480. const char *lookup = (*next == '&') ? next + 1 : next;
  481. *name = next;
  482. if (xindex & AA_X_CHILD) {
  483. /* TODO: switich to parse to get stack of child */
  484. struct aa_profile *new = aa_find_child(profile, lookup);
  485. if (new)
  486. /* release by caller */
  487. return &new->label;
  488. continue;
  489. }
  490. label = aa_label_parse(&profile->label, lookup, GFP_KERNEL,
  491. true, false);
  492. if (!IS_ERR_OR_NULL(label))
  493. /* release by caller */
  494. return label;
  495. }
  496. return NULL;
  497. }
  498. /**
  499. * x_to_label - get target label for a given xindex
  500. * @profile: current profile (NOT NULL)
  501. * @bprm: binprm structure of transitioning task
  502. * @name: name to lookup (NOT NULL)
  503. * @xindex: index into x transition table
  504. * @lookupname: returns: name used in lookup if one was specified (NOT NULL)
  505. * @info: info message if there was an error (NOT NULL)
  506. *
  507. * find label for a transition index
  508. *
  509. * Returns: refcounted label or NULL if not found available
  510. */
  511. static struct aa_label *x_to_label(struct aa_profile *profile,
  512. const struct linux_binprm *bprm,
  513. const char *name, u32 xindex,
  514. const char **lookupname,
  515. const char **info)
  516. {
  517. struct aa_label *new = NULL;
  518. struct aa_label *stack = NULL;
  519. struct aa_ns *ns = profile->ns;
  520. u32 xtype = xindex & AA_X_TYPE_MASK;
  521. /* Used for info checks during fallback handling */
  522. const char *old_info = NULL;
  523. switch (xtype) {
  524. case AA_X_NONE:
  525. /* fail exec unless ix || ux fallback - handled by caller */
  526. *lookupname = NULL;
  527. break;
  528. case AA_X_TABLE:
  529. /* TODO: fix when perm mapping done at unload */
  530. /* released by caller
  531. * if null for both stack and direct want to try fallback
  532. */
  533. new = x_table_lookup(profile, xindex, lookupname);
  534. if (!new || **lookupname != '&')
  535. break;
  536. stack = new;
  537. new = NULL;
  538. fallthrough; /* to X_NAME */
  539. case AA_X_NAME:
  540. if (xindex & AA_X_CHILD)
  541. /* released by caller */
  542. new = find_attach(bprm, ns, &profile->base.profiles,
  543. name, info);
  544. else
  545. /* released by caller */
  546. new = find_attach(bprm, ns, &ns->base.profiles,
  547. name, info);
  548. *lookupname = name;
  549. break;
  550. }
  551. /* fallback transition check */
  552. if (!new) {
  553. if (xindex & AA_X_INHERIT) {
  554. /* (p|c|n)ix - don't change profile but do
  555. * use the newest version
  556. */
  557. if (*info == CONFLICTING_ATTACH_STR) {
  558. *info = CONFLICTING_ATTACH_STR_IX;
  559. } else {
  560. old_info = *info;
  561. *info = "ix fallback";
  562. }
  563. /* no profile && no error */
  564. new = aa_get_newest_label(&profile->label);
  565. } else if (xindex & AA_X_UNCONFINED) {
  566. new = aa_get_newest_label(ns_unconfined(profile->ns));
  567. if (*info == CONFLICTING_ATTACH_STR) {
  568. *info = CONFLICTING_ATTACH_STR_UX;
  569. } else {
  570. old_info = *info;
  571. *info = "ux fallback";
  572. }
  573. }
  574. /* We set old_info on the code paths above where overwriting
  575. * could have happened, so now check if info was set by
  576. * find_attach as well (i.e. whether we actually overwrote)
  577. * and warn accordingly.
  578. */
  579. if (old_info && old_info != CONFLICTING_ATTACH_STR) {
  580. pr_warn_ratelimited(
  581. "AppArmor: find_attach (from profile %s) audit info \"%s\" dropped",
  582. profile->base.hname, old_info);
  583. }
  584. }
  585. if (new && stack) {
  586. /* base the stack on post domain transition */
  587. struct aa_label *base = new;
  588. new = aa_label_merge(base, stack, GFP_KERNEL);
  589. /* null on error */
  590. aa_put_label(base);
  591. }
  592. aa_put_label(stack);
  593. /* released by caller */
  594. return new;
  595. }
  596. static struct aa_label *profile_transition(const struct cred *subj_cred,
  597. struct aa_profile *profile,
  598. const struct linux_binprm *bprm,
  599. char *buffer, struct path_cond *cond,
  600. bool *secure_exec)
  601. {
  602. struct aa_ruleset *rules = profile->label.rules[0];
  603. struct aa_label *new = NULL;
  604. struct aa_profile *new_profile = NULL;
  605. const char *info = NULL, *name = NULL, *target = NULL;
  606. aa_state_t state = rules->file->start[AA_CLASS_FILE];
  607. struct aa_perms perms = {};
  608. bool nonewprivs = false;
  609. int error = 0;
  610. AA_BUG(!profile);
  611. AA_BUG(!bprm);
  612. AA_BUG(!buffer);
  613. error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer,
  614. &name, &info, profile->disconnected);
  615. if (error) {
  616. if (profile_unconfined(profile) ||
  617. (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) {
  618. AA_DEBUG(DEBUG_DOMAIN, "name lookup ix on error");
  619. error = 0;
  620. new = aa_get_newest_label(&profile->label);
  621. }
  622. name = bprm->filename;
  623. goto audit;
  624. }
  625. if (profile_unconfined(profile)) {
  626. new = find_attach(bprm, profile->ns,
  627. &profile->ns->base.profiles, name, &info);
  628. /* info set -> something unusual that we should report
  629. * Currently this is only conflicting attachments, but other
  630. * infos added in the future should also be logged by default
  631. * and only excluded on a case-by-case basis
  632. */
  633. if (info) {
  634. /* Because perms is never used again after this audit
  635. * we don't need to care about clobbering it
  636. */
  637. perms.audit |= MAY_EXEC;
  638. perms.allow |= MAY_EXEC;
  639. /* Don't cause error if auditing fails */
  640. (void) aa_audit_file(subj_cred, profile, &perms,
  641. OP_EXEC, MAY_EXEC, name, target, new, cond->uid,
  642. info, error);
  643. }
  644. if (new) {
  645. AA_DEBUG(DEBUG_DOMAIN, "unconfined attached to new label");
  646. return new;
  647. }
  648. AA_DEBUG(DEBUG_DOMAIN, "unconfined exec no attachment");
  649. return aa_get_newest_label(&profile->label);
  650. }
  651. /* find exec permissions for name */
  652. state = aa_str_perms(rules->file, state, name, cond, &perms);
  653. if (perms.allow & MAY_EXEC) {
  654. /* exec permission determine how to transition */
  655. new = x_to_label(profile, bprm, name, perms.xindex, &target,
  656. &info);
  657. if (new && new->proxy == profile->label.proxy && info) {
  658. /* Force audit on conflicting attachment fallback
  659. * Because perms is never used again after this audit
  660. * we don't need to care about clobbering it
  661. */
  662. if (info == CONFLICTING_ATTACH_STR_IX
  663. || info == CONFLICTING_ATTACH_STR_UX)
  664. perms.audit |= MAY_EXEC;
  665. /* hack ix fallback - improve how this is detected */
  666. goto audit;
  667. } else if (!new) {
  668. if (info) {
  669. pr_warn_ratelimited(
  670. "AppArmor: %s (from profile %s) audit info \"%s\" dropped on missing transition",
  671. __func__, profile->base.hname, info);
  672. }
  673. info = "profile transition not found";
  674. /* remove MAY_EXEC to audit as failure or complaint */
  675. perms.allow &= ~MAY_EXEC;
  676. if (COMPLAIN_MODE(profile)) {
  677. /* create null profile instead of failing */
  678. goto create_learning_profile;
  679. }
  680. error = -EACCES;
  681. }
  682. } else if (COMPLAIN_MODE(profile)) {
  683. create_learning_profile:
  684. /* no exec permission - learning mode */
  685. new_profile = aa_new_learning_profile(profile, false, name,
  686. GFP_KERNEL);
  687. if (!new_profile) {
  688. error = -ENOMEM;
  689. info = "could not create null profile";
  690. } else {
  691. error = -EACCES;
  692. new = &new_profile->label;
  693. }
  694. perms.xindex |= AA_X_UNSAFE;
  695. } else
  696. /* fail exec */
  697. error = -EACCES;
  698. if (!new)
  699. goto audit;
  700. if (!(perms.xindex & AA_X_UNSAFE)) {
  701. if (DEBUG_ON) {
  702. dbg_printk("apparmor: setting AT_SECURE for %s profile=",
  703. name);
  704. aa_label_printk(new, GFP_KERNEL);
  705. dbg_printk("\n");
  706. }
  707. *secure_exec = true;
  708. }
  709. audit:
  710. aa_audit_file(subj_cred, profile, &perms, OP_EXEC, MAY_EXEC, name,
  711. target, new,
  712. cond->uid, info, error);
  713. if (!new || nonewprivs) {
  714. aa_put_label(new);
  715. return ERR_PTR(error);
  716. }
  717. return new;
  718. }
  719. static int profile_onexec(const struct cred *subj_cred,
  720. struct aa_profile *profile, struct aa_label *onexec,
  721. bool stack, const struct linux_binprm *bprm,
  722. char *buffer, struct path_cond *cond,
  723. bool *secure_exec)
  724. {
  725. struct aa_ruleset *rules = profile->label.rules[0];
  726. aa_state_t state = rules->file->start[AA_CLASS_FILE];
  727. struct aa_perms perms = {};
  728. const char *xname = NULL, *info = "change_profile onexec";
  729. int error = -EACCES;
  730. AA_BUG(!profile);
  731. AA_BUG(!onexec);
  732. AA_BUG(!bprm);
  733. AA_BUG(!buffer);
  734. if (profile_unconfined(profile)) {
  735. /* change_profile on exec already granted */
  736. /*
  737. * NOTE: Domain transitions from unconfined are allowed
  738. * even when no_new_privs is set because this always results
  739. * in a further reduction of permissions.
  740. */
  741. return 0;
  742. }
  743. error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer,
  744. &xname, &info, profile->disconnected);
  745. if (error) {
  746. if (profile_unconfined(profile) ||
  747. (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) {
  748. AA_DEBUG(DEBUG_DOMAIN, "name lookup ix on error");
  749. error = 0;
  750. }
  751. xname = bprm->filename;
  752. goto audit;
  753. }
  754. /* find exec permissions for name */
  755. state = aa_str_perms(rules->file, state, xname, cond, &perms);
  756. if (!(perms.allow & AA_MAY_ONEXEC)) {
  757. info = "no change_onexec valid for executable";
  758. goto audit;
  759. }
  760. /* test if this exec can be paired with change_profile onexec.
  761. * onexec permission is linked to exec with a standard pairing
  762. * exec\0change_profile
  763. */
  764. state = aa_dfa_null_transition(rules->file->dfa, state);
  765. error = change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC,
  766. state, &perms);
  767. if (error) {
  768. perms.allow &= ~AA_MAY_ONEXEC;
  769. goto audit;
  770. }
  771. if (!(perms.xindex & AA_X_UNSAFE)) {
  772. if (DEBUG_ON) {
  773. dbg_printk("apparmor: setting AT_SECURE for %s label=",
  774. xname);
  775. aa_label_printk(onexec, GFP_KERNEL);
  776. dbg_printk("\n");
  777. }
  778. *secure_exec = true;
  779. }
  780. audit:
  781. return aa_audit_file(subj_cred, profile, &perms, OP_EXEC,
  782. AA_MAY_ONEXEC, xname,
  783. NULL, onexec, cond->uid, info, error);
  784. }
  785. /* ensure none ns domain transitions are correctly applied with onexec */
  786. static struct aa_label *handle_onexec(const struct cred *subj_cred,
  787. struct aa_label *label,
  788. struct aa_label *onexec, bool stack,
  789. const struct linux_binprm *bprm,
  790. char *buffer, struct path_cond *cond,
  791. bool *unsafe)
  792. {
  793. struct aa_profile *profile;
  794. struct aa_label *new;
  795. int error;
  796. AA_BUG(!label);
  797. AA_BUG(!onexec);
  798. AA_BUG(!bprm);
  799. AA_BUG(!buffer);
  800. /* TODO: determine how much we want to loosen this
  801. * only check profiles in scope for permission to change at exec
  802. */
  803. error = fn_for_each_in_scope(label, profile,
  804. profile_onexec(subj_cred, profile, onexec, stack,
  805. bprm, buffer, cond, unsafe));
  806. if (error)
  807. return ERR_PTR(error);
  808. new = fn_label_build_in_scope(label, profile, GFP_KERNEL,
  809. stack ? aa_label_merge(&profile->label, onexec,
  810. GFP_KERNEL)
  811. : aa_get_newest_label(onexec),
  812. profile_transition(subj_cred, profile, bprm,
  813. buffer, cond, unsafe));
  814. if (new)
  815. return new;
  816. /* TODO: get rid of GLOBAL_ROOT_UID */
  817. error = fn_for_each_in_scope(label, profile,
  818. aa_audit_file(subj_cred, profile, &nullperms,
  819. OP_CHANGE_ONEXEC,
  820. AA_MAY_ONEXEC, bprm->filename, NULL,
  821. onexec, GLOBAL_ROOT_UID,
  822. "failed to build target label", -ENOMEM));
  823. return ERR_PTR(error);
  824. }
  825. /**
  826. * apparmor_bprm_creds_for_exec - Update the new creds on the bprm struct
  827. * @bprm: binprm for the exec (NOT NULL)
  828. *
  829. * Returns: %0 or error on failure
  830. *
  831. * TODO: once the other paths are done see if we can't refactor into a fn
  832. */
  833. int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
  834. {
  835. struct aa_task_ctx *ctx;
  836. struct aa_label *label, *new = NULL;
  837. const struct cred *subj_cred;
  838. struct aa_profile *profile;
  839. char *buffer = NULL;
  840. const char *info = NULL;
  841. int error = 0;
  842. bool unsafe = false;
  843. vfsuid_t vfsuid = i_uid_into_vfsuid(file_mnt_idmap(bprm->file),
  844. file_inode(bprm->file));
  845. struct path_cond cond = {
  846. vfsuid_into_kuid(vfsuid),
  847. file_inode(bprm->file)->i_mode
  848. };
  849. subj_cred = current_cred();
  850. ctx = task_ctx(current);
  851. AA_BUG(!cred_label(bprm->cred));
  852. AA_BUG(!ctx);
  853. label = aa_get_newest_label(cred_label(bprm->cred));
  854. /*
  855. * Detect no new privs being set, and store the label it
  856. * occurred under. Ideally this would happen when nnp
  857. * is set but there isn't a good way to do that yet.
  858. *
  859. * Testing for unconfined must be done before the subset test
  860. */
  861. if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) && !unconfined(label) &&
  862. !ctx->nnp)
  863. ctx->nnp = aa_get_label(label);
  864. /* buffer freed below, name is pointer into buffer */
  865. buffer = aa_get_buffer(false);
  866. if (!buffer) {
  867. error = -ENOMEM;
  868. goto done;
  869. }
  870. /* Test for onexec first as onexec override other x transitions. */
  871. if (ctx->onexec)
  872. new = handle_onexec(subj_cred, label, ctx->onexec, ctx->token,
  873. bprm, buffer, &cond, &unsafe);
  874. else
  875. new = fn_label_build(label, profile, GFP_KERNEL,
  876. profile_transition(subj_cred, profile, bprm,
  877. buffer,
  878. &cond, &unsafe));
  879. AA_BUG(!new);
  880. if (IS_ERR(new)) {
  881. error = PTR_ERR(new);
  882. goto done;
  883. } else if (!new) {
  884. error = -ENOMEM;
  885. goto done;
  886. }
  887. /* Policy has specified a domain transitions. If no_new_privs and
  888. * confined ensure the transition is to confinement that is subset
  889. * of the confinement when the task entered no new privs.
  890. *
  891. * NOTE: Domain transitions from unconfined and to stacked
  892. * subsets are allowed even when no_new_privs is set because this
  893. * always results in a further reduction of permissions.
  894. */
  895. if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) &&
  896. !unconfined(label) &&
  897. !aa_label_is_unconfined_subset(new, ctx->nnp)) {
  898. error = -EPERM;
  899. info = "no new privs";
  900. goto audit;
  901. }
  902. if (bprm->unsafe & LSM_UNSAFE_SHARE) {
  903. /* FIXME: currently don't mediate shared state */
  904. ;
  905. }
  906. if (bprm->unsafe & (LSM_UNSAFE_PTRACE)) {
  907. /* TODO: test needs to be profile of label to new */
  908. error = may_change_ptraced_domain(bprm->cred, new, &info);
  909. if (error)
  910. goto audit;
  911. }
  912. if (unsafe) {
  913. if (DEBUG_ON) {
  914. dbg_printk("setting AT_SECURE for %s label=",
  915. bprm->filename);
  916. aa_label_printk(new, GFP_KERNEL);
  917. dbg_printk("\n");
  918. }
  919. bprm->secureexec = 1;
  920. }
  921. if (label->proxy != new->proxy) {
  922. /* when transitioning clear unsafe personality bits */
  923. if (DEBUG_ON) {
  924. dbg_printk("apparmor: clearing unsafe personality bits. %s label=",
  925. bprm->filename);
  926. aa_label_printk(new, GFP_KERNEL);
  927. dbg_printk("\n");
  928. }
  929. bprm->per_clear |= PER_CLEAR_ON_SETID;
  930. }
  931. aa_put_label(cred_label(bprm->cred));
  932. /* transfer reference, released when cred is freed */
  933. set_cred_label(bprm->cred, new);
  934. done:
  935. aa_put_label(label);
  936. aa_put_buffer(buffer);
  937. return error;
  938. audit:
  939. error = fn_for_each(label, profile,
  940. aa_audit_file(current_cred(), profile, &nullperms,
  941. OP_EXEC, MAY_EXEC,
  942. bprm->filename, NULL, new,
  943. vfsuid_into_kuid(vfsuid), info, error));
  944. aa_put_label(new);
  945. goto done;
  946. }
  947. /*
  948. * Functions for self directed profile change
  949. */
  950. /* helper fn for change_hat
  951. *
  952. * Returns: label for hat transition OR ERR_PTR. Does NOT return NULL
  953. */
  954. static struct aa_label *build_change_hat(const struct cred *subj_cred,
  955. struct aa_profile *profile,
  956. const char *name, bool sibling)
  957. {
  958. struct aa_profile *root, *hat = NULL;
  959. const char *info = NULL;
  960. int error = 0;
  961. if (sibling && PROFILE_IS_HAT(profile)) {
  962. root = aa_get_profile_rcu(&profile->parent);
  963. } else if (!sibling && !PROFILE_IS_HAT(profile)) {
  964. root = aa_get_profile(profile);
  965. } else {
  966. info = "conflicting target types";
  967. error = -EPERM;
  968. goto audit;
  969. }
  970. hat = aa_find_child(root, name);
  971. if (!hat) {
  972. error = -ENOENT;
  973. if (COMPLAIN_MODE(profile)) {
  974. hat = aa_new_learning_profile(profile, true, name,
  975. GFP_KERNEL);
  976. if (!hat) {
  977. info = "failed null profile create";
  978. error = -ENOMEM;
  979. }
  980. }
  981. }
  982. aa_put_profile(root);
  983. audit:
  984. aa_audit_file(subj_cred, profile, &nullperms, OP_CHANGE_HAT,
  985. AA_MAY_CHANGEHAT,
  986. name, hat ? hat->base.hname : NULL,
  987. hat ? &hat->label : NULL, GLOBAL_ROOT_UID, info,
  988. error);
  989. if (!hat || (error && error != -ENOENT))
  990. return ERR_PTR(error);
  991. /* if hat && error - complain mode, already audited and we adjust for
  992. * complain mode allow by returning hat->label
  993. */
  994. return &hat->label;
  995. }
  996. /* helper fn for changing into a hat
  997. *
  998. * Returns: label for hat transition or ERR_PTR. Does not return NULL
  999. */
  1000. static struct aa_label *change_hat(const struct cred *subj_cred,
  1001. struct aa_label *label, const char *hats[],
  1002. int count, int flags)
  1003. {
  1004. struct aa_profile *profile, *root, *hat = NULL;
  1005. struct aa_label *new;
  1006. struct label_it it;
  1007. bool sibling = false;
  1008. const char *name, *info = NULL;
  1009. int i, error;
  1010. AA_BUG(!label);
  1011. AA_BUG(!hats);
  1012. AA_BUG(count < 1);
  1013. if (PROFILE_IS_HAT(labels_profile(label)))
  1014. sibling = true;
  1015. /*find first matching hat */
  1016. for (i = 0; i < count && !hat; i++) {
  1017. name = hats[i];
  1018. label_for_each_in_scope(it, labels_ns(label), label, profile) {
  1019. if (sibling && PROFILE_IS_HAT(profile)) {
  1020. root = aa_get_profile_rcu(&profile->parent);
  1021. } else if (!sibling && !PROFILE_IS_HAT(profile)) {
  1022. root = aa_get_profile(profile);
  1023. } else { /* conflicting change type */
  1024. info = "conflicting targets types";
  1025. error = -EPERM;
  1026. goto fail;
  1027. }
  1028. hat = aa_find_child(root, name);
  1029. aa_put_profile(root);
  1030. if (!hat) {
  1031. if (!COMPLAIN_MODE(profile))
  1032. goto outer_continue;
  1033. /* complain mode succeed as if hat */
  1034. } else if (!PROFILE_IS_HAT(hat)) {
  1035. info = "target not hat";
  1036. error = -EPERM;
  1037. aa_put_profile(hat);
  1038. goto fail;
  1039. }
  1040. aa_put_profile(hat);
  1041. }
  1042. /* found a hat for all profiles in ns */
  1043. goto build;
  1044. outer_continue:
  1045. ;
  1046. }
  1047. /* no hats that match, find appropriate error
  1048. *
  1049. * In complain mode audit of the failure is based off of the first
  1050. * hat supplied. This is done due how userspace interacts with
  1051. * change_hat.
  1052. */
  1053. name = NULL;
  1054. label_for_each_in_scope(it, labels_ns(label), label, profile) {
  1055. if (!list_empty(&profile->base.profiles)) {
  1056. info = "hat not found";
  1057. error = -ENOENT;
  1058. goto fail;
  1059. }
  1060. }
  1061. info = "no hats defined";
  1062. error = -ECHILD;
  1063. fail:
  1064. label_for_each_in_scope(it, labels_ns(label), label, profile) {
  1065. /*
  1066. * no target as it has failed to be found or built
  1067. *
  1068. * change_hat uses probing and should not log failures
  1069. * related to missing hats
  1070. */
  1071. /* TODO: get rid of GLOBAL_ROOT_UID */
  1072. if (count > 1 || COMPLAIN_MODE(profile)) {
  1073. aa_audit_file(subj_cred, profile, &nullperms,
  1074. OP_CHANGE_HAT,
  1075. AA_MAY_CHANGEHAT, name, NULL, NULL,
  1076. GLOBAL_ROOT_UID, info, error);
  1077. }
  1078. }
  1079. return ERR_PTR(error);
  1080. build:
  1081. new = fn_label_build_in_scope(label, profile, GFP_KERNEL,
  1082. build_change_hat(subj_cred, profile, name,
  1083. sibling),
  1084. aa_get_label(&profile->label));
  1085. if (!new) {
  1086. info = "label build failed";
  1087. error = -ENOMEM;
  1088. goto fail;
  1089. } /* else if (IS_ERR) build_change_hat has logged error so return new */
  1090. return new;
  1091. }
  1092. /**
  1093. * aa_change_hat - change hat to/from subprofile
  1094. * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0)
  1095. * @count: number of hat names in @hats
  1096. * @token: magic value to validate the hat change
  1097. * @flags: flags affecting behavior of the change
  1098. *
  1099. * Returns %0 on success, error otherwise.
  1100. *
  1101. * Change to the first profile specified in @hats that exists, and store
  1102. * the @hat_magic in the current task context. If the count == 0 and the
  1103. * @token matches that stored in the current task context, return to the
  1104. * top level profile.
  1105. *
  1106. * change_hat only applies to profiles in the current ns, and each profile
  1107. * in the ns must make the same transition otherwise change_hat will fail.
  1108. */
  1109. int aa_change_hat(const char *hats[], int count, u64 token, int flags)
  1110. {
  1111. const struct cred *subj_cred;
  1112. struct aa_task_ctx *ctx = task_ctx(current);
  1113. struct aa_label *label, *previous, *new = NULL, *target = NULL;
  1114. struct aa_profile *profile;
  1115. struct aa_perms perms = {};
  1116. const char *info = NULL;
  1117. int error = 0;
  1118. /* released below */
  1119. subj_cred = get_current_cred();
  1120. label = aa_get_newest_cred_label(subj_cred);
  1121. previous = aa_get_newest_label(ctx->previous);
  1122. /*
  1123. * Detect no new privs being set, and store the label it
  1124. * occurred under. Ideally this would happen when nnp
  1125. * is set but there isn't a good way to do that yet.
  1126. *
  1127. * Testing for unconfined must be done before the subset test
  1128. */
  1129. if (task_no_new_privs(current) && !unconfined(label) && !ctx->nnp)
  1130. ctx->nnp = aa_get_label(label);
  1131. /* return -EPERM when unconfined doesn't have children to avoid
  1132. * changing the traditional error code for unconfined.
  1133. */
  1134. if (unconfined(label)) {
  1135. struct label_it i;
  1136. bool empty = true;
  1137. rcu_read_lock();
  1138. label_for_each_in_scope(i, labels_ns(label), label, profile) {
  1139. empty &= list_empty(&profile->base.profiles);
  1140. }
  1141. rcu_read_unlock();
  1142. if (empty) {
  1143. info = "unconfined can not change_hat";
  1144. error = -EPERM;
  1145. goto fail;
  1146. }
  1147. }
  1148. if (count) {
  1149. new = change_hat(subj_cred, label, hats, count, flags);
  1150. AA_BUG(!new);
  1151. if (IS_ERR(new)) {
  1152. error = PTR_ERR(new);
  1153. new = NULL;
  1154. /* already audited */
  1155. goto out;
  1156. }
  1157. /* target cred is the same as current except new label */
  1158. error = may_change_ptraced_domain(subj_cred, new, &info);
  1159. if (error)
  1160. goto fail;
  1161. /*
  1162. * no new privs prevents domain transitions that would
  1163. * reduce restrictions.
  1164. */
  1165. if (task_no_new_privs(current) && !unconfined(label) &&
  1166. !aa_label_is_unconfined_subset(new, ctx->nnp)) {
  1167. /* not an apparmor denial per se, so don't log it */
  1168. AA_DEBUG(DEBUG_DOMAIN,
  1169. "no_new_privs - change_hat denied");
  1170. error = -EPERM;
  1171. goto out;
  1172. }
  1173. if (flags & AA_CHANGE_TEST)
  1174. goto out;
  1175. target = new;
  1176. error = aa_set_current_hat(new, token);
  1177. if (error == -EACCES)
  1178. /* kill task in case of brute force attacks */
  1179. goto kill;
  1180. } else if (previous && !(flags & AA_CHANGE_TEST)) {
  1181. /*
  1182. * no new privs prevents domain transitions that would
  1183. * reduce restrictions.
  1184. */
  1185. if (task_no_new_privs(current) && !unconfined(label) &&
  1186. !aa_label_is_unconfined_subset(previous, ctx->nnp)) {
  1187. /* not an apparmor denial per se, so don't log it */
  1188. AA_DEBUG(DEBUG_DOMAIN,
  1189. "no_new_privs - change_hat denied");
  1190. error = -EPERM;
  1191. goto out;
  1192. }
  1193. /* Return to saved label. Kill task if restore fails
  1194. * to avoid brute force attacks
  1195. */
  1196. target = previous;
  1197. error = aa_restore_previous_label(token);
  1198. if (error) {
  1199. if (error == -EACCES)
  1200. goto kill;
  1201. goto fail;
  1202. }
  1203. } /* else ignore @flags && restores when there is no saved profile */
  1204. out:
  1205. aa_put_label(new);
  1206. aa_put_label(previous);
  1207. aa_put_label(label);
  1208. put_cred(subj_cred);
  1209. return error;
  1210. kill:
  1211. info = "failed token match";
  1212. perms.kill = AA_MAY_CHANGEHAT;
  1213. fail:
  1214. fn_for_each_in_scope(label, profile,
  1215. aa_audit_file(subj_cred, profile, &perms, OP_CHANGE_HAT,
  1216. AA_MAY_CHANGEHAT, NULL, NULL, target,
  1217. GLOBAL_ROOT_UID, info, error));
  1218. goto out;
  1219. }
  1220. static int change_profile_perms_wrapper(const char *op, const char *name,
  1221. const struct cred *subj_cred,
  1222. struct aa_profile *profile,
  1223. struct aa_label *target, bool stack,
  1224. u32 request, struct aa_perms *perms)
  1225. {
  1226. struct aa_ruleset *rules = profile->label.rules[0];
  1227. const char *info = NULL;
  1228. int error = 0;
  1229. if (!error)
  1230. error = change_profile_perms(profile, target, stack, request,
  1231. rules->file->start[AA_CLASS_FILE],
  1232. perms);
  1233. if (error)
  1234. error = aa_audit_file(subj_cred, profile, perms, op, request,
  1235. name,
  1236. NULL, target, GLOBAL_ROOT_UID, info,
  1237. error);
  1238. return error;
  1239. }
  1240. static const char *stack_msg = "change_profile unprivileged unconfined converted to stacking";
  1241. /**
  1242. * aa_change_profile - perform a one-way profile transition
  1243. * @fqname: name of profile may include namespace (NOT NULL)
  1244. * @flags: flags affecting change behavior
  1245. *
  1246. * Change to new profile @name. Unlike with hats, there is no way
  1247. * to change back. If @name isn't specified the current profile name is
  1248. * used.
  1249. * If @onexec then the transition is delayed until
  1250. * the next exec.
  1251. *
  1252. * Returns %0 on success, error otherwise.
  1253. */
  1254. int aa_change_profile(const char *fqname, int flags)
  1255. {
  1256. struct aa_label *label, *new = NULL, *target = NULL;
  1257. struct aa_profile *profile;
  1258. struct aa_perms perms = {};
  1259. const char *info = NULL;
  1260. const char *auditname = fqname; /* retain leading & if stack */
  1261. bool stack = flags & AA_CHANGE_STACK;
  1262. struct aa_task_ctx *ctx = task_ctx(current);
  1263. const struct cred *subj_cred = get_current_cred();
  1264. int error = 0;
  1265. char *op;
  1266. u32 request;
  1267. label = aa_get_current_label();
  1268. /*
  1269. * Detect no new privs being set, and store the label it
  1270. * occurred under. Ideally this would happen when nnp
  1271. * is set but there isn't a good way to do that yet.
  1272. *
  1273. * Testing for unconfined must be done before the subset test
  1274. */
  1275. if (task_no_new_privs(current) && !unconfined(label) && !ctx->nnp)
  1276. ctx->nnp = aa_get_label(label);
  1277. if (!fqname || !*fqname) {
  1278. aa_put_label(label);
  1279. AA_DEBUG(DEBUG_DOMAIN, "no profile name");
  1280. return -EINVAL;
  1281. }
  1282. if (flags & AA_CHANGE_ONEXEC) {
  1283. request = AA_MAY_ONEXEC;
  1284. if (stack)
  1285. op = OP_STACK_ONEXEC;
  1286. else
  1287. op = OP_CHANGE_ONEXEC;
  1288. } else {
  1289. request = AA_MAY_CHANGE_PROFILE;
  1290. if (stack)
  1291. op = OP_STACK;
  1292. else
  1293. op = OP_CHANGE_PROFILE;
  1294. }
  1295. /* This should move to a per profile test. Requires pushing build
  1296. * into callback
  1297. */
  1298. if (!stack && unconfined(label) &&
  1299. label == &labels_ns(label)->unconfined->label &&
  1300. aa_unprivileged_unconfined_restricted &&
  1301. /* TODO: refactor so this check is a fn */
  1302. cap_capable(current_cred(), &init_user_ns, CAP_MAC_OVERRIDE,
  1303. CAP_OPT_NOAUDIT)) {
  1304. /* regardless of the request in this case apparmor
  1305. * stacks against unconfined so admin set policy can't be
  1306. * by-passed
  1307. */
  1308. stack = true;
  1309. perms.audit = request;
  1310. (void) fn_for_each_in_scope(label, profile,
  1311. aa_audit_file(subj_cred, profile, &perms, op,
  1312. request, auditname, NULL, target,
  1313. GLOBAL_ROOT_UID, stack_msg, 0));
  1314. perms.audit = 0;
  1315. }
  1316. if (*fqname == '&') {
  1317. stack = true;
  1318. /* don't have label_parse() do stacking */
  1319. fqname++;
  1320. }
  1321. target = aa_label_parse(label, fqname, GFP_KERNEL, true, false);
  1322. if (IS_ERR(target)) {
  1323. struct aa_profile *tprofile;
  1324. info = "label not found";
  1325. error = PTR_ERR(target);
  1326. target = NULL;
  1327. /*
  1328. * TODO: fixme using labels_profile is not right - do profile
  1329. * per complain profile
  1330. */
  1331. if ((flags & AA_CHANGE_TEST) ||
  1332. !COMPLAIN_MODE(labels_profile(label)))
  1333. goto audit;
  1334. /* released below */
  1335. tprofile = aa_new_learning_profile(labels_profile(label), false,
  1336. fqname, GFP_KERNEL);
  1337. if (!tprofile) {
  1338. info = "failed null profile create";
  1339. error = -ENOMEM;
  1340. goto audit;
  1341. }
  1342. target = &tprofile->label;
  1343. goto check;
  1344. }
  1345. /*
  1346. * self directed transitions only apply to current policy ns
  1347. * TODO: currently requiring perms for stacking and straight change
  1348. * stacking doesn't strictly need this. Determine how much
  1349. * we want to loosen this restriction for stacking
  1350. *
  1351. * if (!stack) {
  1352. */
  1353. error = fn_for_each_in_scope(label, profile,
  1354. change_profile_perms_wrapper(op, auditname,
  1355. subj_cred,
  1356. profile, target, stack,
  1357. request, &perms));
  1358. if (error)
  1359. /* auditing done in change_profile_perms_wrapper */
  1360. goto out;
  1361. /* } */
  1362. check:
  1363. /* check if tracing task is allowed to trace target domain */
  1364. error = may_change_ptraced_domain(subj_cred, target, &info);
  1365. if (error && !fn_for_each_in_scope(label, profile,
  1366. COMPLAIN_MODE(profile)))
  1367. goto audit;
  1368. /* TODO: add permission check to allow this
  1369. * if ((flags & AA_CHANGE_ONEXEC) && !current_is_single_threaded()) {
  1370. * info = "not a single threaded task";
  1371. * error = -EACCES;
  1372. * goto audit;
  1373. * }
  1374. */
  1375. if (flags & AA_CHANGE_TEST)
  1376. goto out;
  1377. /* stacking is always a subset, so only check the nonstack case */
  1378. if (!stack) {
  1379. new = fn_label_build_in_scope(label, profile, GFP_KERNEL,
  1380. aa_get_label(target),
  1381. aa_get_label(&profile->label));
  1382. /*
  1383. * no new privs prevents domain transitions that would
  1384. * reduce restrictions.
  1385. */
  1386. if (task_no_new_privs(current) && !unconfined(label) &&
  1387. !aa_label_is_unconfined_subset(new, ctx->nnp)) {
  1388. /* not an apparmor denial per se, so don't log it */
  1389. AA_DEBUG(DEBUG_DOMAIN,
  1390. "no_new_privs - change_hat denied");
  1391. error = -EPERM;
  1392. goto out;
  1393. }
  1394. }
  1395. if (!(flags & AA_CHANGE_ONEXEC)) {
  1396. /* only transition profiles in the current ns */
  1397. if (stack)
  1398. new = aa_label_merge(label, target, GFP_KERNEL);
  1399. if (IS_ERR_OR_NULL(new)) {
  1400. info = "failed to build target label";
  1401. if (!new)
  1402. error = -ENOMEM;
  1403. else
  1404. error = PTR_ERR(new);
  1405. new = NULL;
  1406. perms.allow = 0;
  1407. goto audit;
  1408. }
  1409. error = aa_replace_current_label(new);
  1410. } else {
  1411. if (new) {
  1412. aa_put_label(new);
  1413. new = NULL;
  1414. }
  1415. /* full transition will be built in exec path */
  1416. aa_set_current_onexec(target, stack);
  1417. }
  1418. audit:
  1419. error = fn_for_each_in_scope(label, profile,
  1420. aa_audit_file(subj_cred,
  1421. profile, &perms, op, request, auditname,
  1422. NULL, new ? new : target,
  1423. GLOBAL_ROOT_UID, info, error));
  1424. out:
  1425. aa_put_label(new);
  1426. aa_put_label(target);
  1427. aa_put_label(label);
  1428. put_cred(subj_cred);
  1429. return error;
  1430. }