mount.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * AppArmor security module
  4. *
  5. * This file contains AppArmor mediation of files
  6. *
  7. * Copyright (C) 1998-2008 Novell/SUSE
  8. * Copyright 2009-2017 Canonical Ltd.
  9. */
  10. #include <linux/fs.h>
  11. #include <linux/mount.h>
  12. #include <linux/namei.h>
  13. #include <uapi/linux/mount.h>
  14. #include "include/apparmor.h"
  15. #include "include/audit.h"
  16. #include "include/cred.h"
  17. #include "include/domain.h"
  18. #include "include/file.h"
  19. #include "include/match.h"
  20. #include "include/mount.h"
  21. #include "include/path.h"
  22. #include "include/policy.h"
  23. static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
  24. {
  25. if (flags & MS_RDONLY)
  26. audit_log_format(ab, "ro");
  27. else
  28. audit_log_format(ab, "rw");
  29. if (flags & MS_NOSUID)
  30. audit_log_format(ab, ", nosuid");
  31. if (flags & MS_NODEV)
  32. audit_log_format(ab, ", nodev");
  33. if (flags & MS_NOEXEC)
  34. audit_log_format(ab, ", noexec");
  35. if (flags & MS_SYNCHRONOUS)
  36. audit_log_format(ab, ", sync");
  37. if (flags & MS_REMOUNT)
  38. audit_log_format(ab, ", remount");
  39. if (flags & MS_MANDLOCK)
  40. audit_log_format(ab, ", mand");
  41. if (flags & MS_DIRSYNC)
  42. audit_log_format(ab, ", dirsync");
  43. if (flags & MS_NOSYMFOLLOW)
  44. audit_log_format(ab, ", nosymfollow");
  45. if (flags & MS_NOATIME)
  46. audit_log_format(ab, ", noatime");
  47. if (flags & MS_NODIRATIME)
  48. audit_log_format(ab, ", nodiratime");
  49. if (flags & MS_BIND)
  50. audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
  51. if (flags & MS_MOVE)
  52. audit_log_format(ab, ", move");
  53. if (flags & MS_SILENT)
  54. audit_log_format(ab, ", silent");
  55. if (flags & MS_POSIXACL)
  56. audit_log_format(ab, ", acl");
  57. if (flags & MS_UNBINDABLE)
  58. audit_log_format(ab, flags & MS_REC ? ", runbindable" :
  59. ", unbindable");
  60. if (flags & MS_PRIVATE)
  61. audit_log_format(ab, flags & MS_REC ? ", rprivate" :
  62. ", private");
  63. if (flags & MS_SLAVE)
  64. audit_log_format(ab, flags & MS_REC ? ", rslave" :
  65. ", slave");
  66. if (flags & MS_SHARED)
  67. audit_log_format(ab, flags & MS_REC ? ", rshared" :
  68. ", shared");
  69. if (flags & MS_RELATIME)
  70. audit_log_format(ab, ", relatime");
  71. if (flags & MS_I_VERSION)
  72. audit_log_format(ab, ", iversion");
  73. if (flags & MS_STRICTATIME)
  74. audit_log_format(ab, ", strictatime");
  75. if (flags & MS_NOUSER)
  76. audit_log_format(ab, ", nouser");
  77. }
  78. /**
  79. * audit_cb - call back for mount specific audit fields
  80. * @ab: audit_buffer (NOT NULL)
  81. * @va: audit struct to audit values of (NOT NULL)
  82. */
  83. static void audit_cb(struct audit_buffer *ab, void *va)
  84. {
  85. struct common_audit_data *sa = va;
  86. struct apparmor_audit_data *ad = aad(sa);
  87. if (ad->mnt.type) {
  88. audit_log_format(ab, " fstype=");
  89. audit_log_untrustedstring(ab, ad->mnt.type);
  90. }
  91. if (ad->mnt.src_name) {
  92. audit_log_format(ab, " srcname=");
  93. audit_log_untrustedstring(ab, ad->mnt.src_name);
  94. }
  95. if (ad->mnt.trans) {
  96. audit_log_format(ab, " trans=");
  97. audit_log_untrustedstring(ab, ad->mnt.trans);
  98. }
  99. if (ad->mnt.flags) {
  100. audit_log_format(ab, " flags=\"");
  101. audit_mnt_flags(ab, ad->mnt.flags);
  102. audit_log_format(ab, "\"");
  103. }
  104. if (ad->mnt.data) {
  105. audit_log_format(ab, " options=");
  106. audit_log_untrustedstring(ab, ad->mnt.data);
  107. }
  108. }
  109. /**
  110. * audit_mount - handle the auditing of mount operations
  111. * @subj_cred: cred of the subject
  112. * @profile: the profile being enforced (NOT NULL)
  113. * @op: operation being mediated (NOT NULL)
  114. * @name: name of object being mediated (MAYBE NULL)
  115. * @src_name: src_name of object being mediated (MAYBE_NULL)
  116. * @type: type of filesystem (MAYBE_NULL)
  117. * @trans: name of trans (MAYBE NULL)
  118. * @flags: filesystem independent mount flags
  119. * @data: filesystem mount flags
  120. * @request: permissions requested
  121. * @perms: the permissions computed for the request (NOT NULL)
  122. * @info: extra information message (MAYBE NULL)
  123. * @error: 0 if operation allowed else failure error code
  124. *
  125. * Returns: %0 or error on failure
  126. */
  127. static int audit_mount(const struct cred *subj_cred,
  128. struct aa_profile *profile, const char *op,
  129. const char *name, const char *src_name,
  130. const char *type, const char *trans,
  131. unsigned long flags, const void *data, u32 request,
  132. struct aa_perms *perms, const char *info, int error)
  133. {
  134. int audit_type = AUDIT_APPARMOR_AUTO;
  135. DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_MOUNT, op);
  136. if (likely(!error)) {
  137. u32 mask = perms->audit;
  138. if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
  139. mask = 0xffff;
  140. /* mask off perms that are not being force audited */
  141. request &= mask;
  142. if (likely(!request))
  143. return 0;
  144. audit_type = AUDIT_APPARMOR_AUDIT;
  145. } else {
  146. /* only report permissions that were denied */
  147. request = request & ~perms->allow;
  148. if (request & perms->kill)
  149. audit_type = AUDIT_APPARMOR_KILL;
  150. /* quiet known rejects, assumes quiet and kill do not overlap */
  151. if ((request & perms->quiet) &&
  152. AUDIT_MODE(profile) != AUDIT_NOQUIET &&
  153. AUDIT_MODE(profile) != AUDIT_ALL)
  154. request &= ~perms->quiet;
  155. if (!request)
  156. return error;
  157. }
  158. ad.subj_cred = subj_cred;
  159. ad.name = name;
  160. ad.mnt.src_name = src_name;
  161. ad.mnt.type = type;
  162. ad.mnt.trans = trans;
  163. ad.mnt.flags = flags;
  164. if (data && (perms->audit & AA_AUDIT_DATA))
  165. ad.mnt.data = data;
  166. ad.info = info;
  167. ad.error = error;
  168. return aa_audit(audit_type, profile, &ad, audit_cb);
  169. }
  170. /**
  171. * match_mnt_flags - Do an ordered match on mount flags
  172. * @dfa: dfa to match against
  173. * @state: state to start in
  174. * @flags: mount flags to match against
  175. *
  176. * Mount flags are encoded as an ordered match. This is done instead of
  177. * checking against a simple bitmask, to allow for logical operations
  178. * on the flags.
  179. *
  180. * Returns: next state after flags match
  181. */
  182. static aa_state_t match_mnt_flags(struct aa_dfa *dfa, aa_state_t state,
  183. unsigned long flags)
  184. {
  185. unsigned int i;
  186. for (i = 0; i <= 31 ; ++i) {
  187. if ((1 << i) & flags)
  188. state = aa_dfa_next(dfa, state, i + 1);
  189. }
  190. return state;
  191. }
  192. static const char * const mnt_info_table[] = {
  193. "match succeeded",
  194. "failed mntpnt match",
  195. "failed srcname match",
  196. "failed type match",
  197. "failed flags match",
  198. "failed data match",
  199. "failed perms check"
  200. };
  201. /*
  202. * Returns 0 on success else element that match failed in, this is the
  203. * index into the mnt_info_table above
  204. */
  205. static int do_match_mnt(struct aa_policydb *policy, aa_state_t start,
  206. const char *mntpnt, const char *devname,
  207. const char *type, unsigned long flags,
  208. void *data, bool binary, struct aa_perms *perms)
  209. {
  210. aa_state_t state;
  211. AA_BUG(!policy);
  212. AA_BUG(!policy->dfa);
  213. AA_BUG(!policy->perms);
  214. AA_BUG(!perms);
  215. state = aa_dfa_match(policy->dfa, start, mntpnt);
  216. state = aa_dfa_null_transition(policy->dfa, state);
  217. if (!state)
  218. return 1;
  219. if (devname)
  220. state = aa_dfa_match(policy->dfa, state, devname);
  221. state = aa_dfa_null_transition(policy->dfa, state);
  222. if (!state)
  223. return 2;
  224. if (type)
  225. state = aa_dfa_match(policy->dfa, state, type);
  226. state = aa_dfa_null_transition(policy->dfa, state);
  227. if (!state)
  228. return 3;
  229. state = match_mnt_flags(policy->dfa, state, flags);
  230. if (!state)
  231. return 4;
  232. *perms = *aa_lookup_perms(policy, state);
  233. if (perms->allow & AA_MAY_MOUNT)
  234. return 0;
  235. /* only match data if not binary and the DFA flags data is expected */
  236. if (data && !binary && (perms->allow & AA_MNT_CONT_MATCH)) {
  237. state = aa_dfa_null_transition(policy->dfa, state);
  238. if (!state)
  239. return 4;
  240. state = aa_dfa_match(policy->dfa, state, data);
  241. if (!state)
  242. return 5;
  243. *perms = *aa_lookup_perms(policy, state);
  244. if (perms->allow & AA_MAY_MOUNT)
  245. return 0;
  246. }
  247. /* failed at perms check, don't confuse with flags match */
  248. return 6;
  249. }
  250. static int path_flags(struct aa_profile *profile, const struct path *path)
  251. {
  252. AA_BUG(!profile);
  253. AA_BUG(!path);
  254. return profile->path_flags |
  255. (S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0);
  256. }
  257. /**
  258. * match_mnt_path_str - handle path matching for mount
  259. * @subj_cred: cred of confined subject
  260. * @profile: the confining profile
  261. * @mntpath: for the mntpnt (NOT NULL)
  262. * @buffer: buffer to be used to lookup mntpath
  263. * @devname: string for the devname/src_name (MAY BE NULL OR ERRPTR)
  264. * @type: string for the dev type (MAYBE NULL)
  265. * @flags: mount flags to match
  266. * @data: fs mount data (MAYBE NULL)
  267. * @binary: whether @data is binary
  268. * @devinfo: error str if (IS_ERR(@devname))
  269. *
  270. * Returns: 0 on success else error
  271. */
  272. static int match_mnt_path_str(const struct cred *subj_cred,
  273. struct aa_profile *profile,
  274. const struct path *mntpath, char *buffer,
  275. const char *devname, const char *type,
  276. unsigned long flags, void *data, bool binary,
  277. const char *devinfo)
  278. {
  279. struct aa_perms perms = { };
  280. const char *mntpnt = NULL, *info = NULL;
  281. struct aa_ruleset *rules = list_first_entry(&profile->rules,
  282. typeof(*rules), list);
  283. int pos, error;
  284. AA_BUG(!profile);
  285. AA_BUG(!mntpath);
  286. AA_BUG(!buffer);
  287. if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT))
  288. return 0;
  289. error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer,
  290. &mntpnt, &info, profile->disconnected);
  291. if (error)
  292. goto audit;
  293. if (IS_ERR(devname)) {
  294. error = PTR_ERR(devname);
  295. devname = NULL;
  296. info = devinfo;
  297. goto audit;
  298. }
  299. error = -EACCES;
  300. pos = do_match_mnt(rules->policy,
  301. rules->policy->start[AA_CLASS_MOUNT],
  302. mntpnt, devname, type, flags, data, binary, &perms);
  303. if (pos) {
  304. info = mnt_info_table[pos];
  305. goto audit;
  306. }
  307. error = 0;
  308. audit:
  309. return audit_mount(subj_cred, profile, OP_MOUNT, mntpnt, devname,
  310. type, NULL,
  311. flags, data, AA_MAY_MOUNT, &perms, info, error);
  312. }
  313. /**
  314. * match_mnt - handle path matching for mount
  315. * @subj_cred: cred of the subject
  316. * @profile: the confining profile
  317. * @path: for the mntpnt (NOT NULL)
  318. * @buffer: buffer to be used to lookup mntpath
  319. * @devpath: path devname/src_name (MAYBE NULL)
  320. * @devbuffer: buffer to be used to lookup devname/src_name
  321. * @type: string for the dev type (MAYBE NULL)
  322. * @flags: mount flags to match
  323. * @data: fs mount data (MAYBE NULL)
  324. * @binary: whether @data is binary
  325. *
  326. * Returns: 0 on success else error
  327. */
  328. static int match_mnt(const struct cred *subj_cred,
  329. struct aa_profile *profile, const struct path *path,
  330. char *buffer, const struct path *devpath, char *devbuffer,
  331. const char *type, unsigned long flags, void *data,
  332. bool binary)
  333. {
  334. const char *devname = NULL, *info = NULL;
  335. struct aa_ruleset *rules = list_first_entry(&profile->rules,
  336. typeof(*rules), list);
  337. int error = -EACCES;
  338. AA_BUG(!profile);
  339. AA_BUG(devpath && !devbuffer);
  340. if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT))
  341. return 0;
  342. if (devpath) {
  343. error = aa_path_name(devpath, path_flags(profile, devpath),
  344. devbuffer, &devname, &info,
  345. profile->disconnected);
  346. if (error)
  347. devname = ERR_PTR(error);
  348. }
  349. return match_mnt_path_str(subj_cred, profile, path, buffer, devname,
  350. type, flags, data, binary, info);
  351. }
  352. int aa_remount(const struct cred *subj_cred,
  353. struct aa_label *label, const struct path *path,
  354. unsigned long flags, void *data)
  355. {
  356. struct aa_profile *profile;
  357. char *buffer = NULL;
  358. bool binary;
  359. int error;
  360. AA_BUG(!label);
  361. AA_BUG(!path);
  362. binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
  363. buffer = aa_get_buffer(false);
  364. if (!buffer)
  365. return -ENOMEM;
  366. error = fn_for_each_confined(label, profile,
  367. match_mnt(subj_cred, profile, path, buffer, NULL,
  368. NULL, NULL,
  369. flags, data, binary));
  370. aa_put_buffer(buffer);
  371. return error;
  372. }
  373. int aa_bind_mount(const struct cred *subj_cred,
  374. struct aa_label *label, const struct path *path,
  375. const char *dev_name, unsigned long flags)
  376. {
  377. struct aa_profile *profile;
  378. char *buffer = NULL, *old_buffer = NULL;
  379. struct path old_path;
  380. int error;
  381. AA_BUG(!label);
  382. AA_BUG(!path);
  383. if (!dev_name || !*dev_name)
  384. return -EINVAL;
  385. flags &= MS_REC | MS_BIND;
  386. error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
  387. if (error)
  388. return error;
  389. buffer = aa_get_buffer(false);
  390. old_buffer = aa_get_buffer(false);
  391. error = -ENOMEM;
  392. if (!buffer || !old_buffer)
  393. goto out;
  394. error = fn_for_each_confined(label, profile,
  395. match_mnt(subj_cred, profile, path, buffer, &old_path,
  396. old_buffer, NULL, flags, NULL, false));
  397. out:
  398. aa_put_buffer(buffer);
  399. aa_put_buffer(old_buffer);
  400. path_put(&old_path);
  401. return error;
  402. }
  403. int aa_mount_change_type(const struct cred *subj_cred,
  404. struct aa_label *label, const struct path *path,
  405. unsigned long flags)
  406. {
  407. struct aa_profile *profile;
  408. char *buffer = NULL;
  409. int error;
  410. AA_BUG(!label);
  411. AA_BUG(!path);
  412. /* These are the flags allowed by do_change_type() */
  413. flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
  414. MS_UNBINDABLE);
  415. buffer = aa_get_buffer(false);
  416. if (!buffer)
  417. return -ENOMEM;
  418. error = fn_for_each_confined(label, profile,
  419. match_mnt(subj_cred, profile, path, buffer, NULL,
  420. NULL, NULL,
  421. flags, NULL, false));
  422. aa_put_buffer(buffer);
  423. return error;
  424. }
  425. int aa_move_mount(const struct cred *subj_cred,
  426. struct aa_label *label, const struct path *from_path,
  427. const struct path *to_path)
  428. {
  429. struct aa_profile *profile;
  430. char *to_buffer = NULL, *from_buffer = NULL;
  431. int error;
  432. AA_BUG(!label);
  433. AA_BUG(!from_path);
  434. AA_BUG(!to_path);
  435. to_buffer = aa_get_buffer(false);
  436. from_buffer = aa_get_buffer(false);
  437. error = -ENOMEM;
  438. if (!to_buffer || !from_buffer)
  439. goto out;
  440. if (!our_mnt(from_path->mnt))
  441. /* moving a mount detached from the namespace */
  442. from_path = NULL;
  443. error = fn_for_each_confined(label, profile,
  444. match_mnt(subj_cred, profile, to_path, to_buffer,
  445. from_path, from_buffer,
  446. NULL, MS_MOVE, NULL, false));
  447. out:
  448. aa_put_buffer(to_buffer);
  449. aa_put_buffer(from_buffer);
  450. return error;
  451. }
  452. int aa_move_mount_old(const struct cred *subj_cred, struct aa_label *label,
  453. const struct path *path, const char *orig_name)
  454. {
  455. struct path old_path;
  456. int error;
  457. if (!orig_name || !*orig_name)
  458. return -EINVAL;
  459. error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
  460. if (error)
  461. return error;
  462. error = aa_move_mount(subj_cred, label, &old_path, path);
  463. path_put(&old_path);
  464. return error;
  465. }
  466. int aa_new_mount(const struct cred *subj_cred, struct aa_label *label,
  467. const char *dev_name, const struct path *path,
  468. const char *type, unsigned long flags, void *data)
  469. {
  470. struct aa_profile *profile;
  471. char *buffer = NULL, *dev_buffer = NULL;
  472. bool binary = true;
  473. int error;
  474. int requires_dev = 0;
  475. struct path tmp_path, *dev_path = NULL;
  476. AA_BUG(!label);
  477. AA_BUG(!path);
  478. if (type) {
  479. struct file_system_type *fstype;
  480. fstype = get_fs_type(type);
  481. if (!fstype)
  482. return -ENODEV;
  483. binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
  484. requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
  485. put_filesystem(fstype);
  486. if (requires_dev) {
  487. if (!dev_name || !*dev_name)
  488. return -ENOENT;
  489. error = kern_path(dev_name, LOOKUP_FOLLOW, &tmp_path);
  490. if (error)
  491. return error;
  492. dev_path = &tmp_path;
  493. }
  494. }
  495. buffer = aa_get_buffer(false);
  496. if (!buffer) {
  497. error = -ENOMEM;
  498. goto out;
  499. }
  500. if (dev_path) {
  501. dev_buffer = aa_get_buffer(false);
  502. if (!dev_buffer) {
  503. error = -ENOMEM;
  504. goto out;
  505. }
  506. error = fn_for_each_confined(label, profile,
  507. match_mnt(subj_cred, profile, path, buffer,
  508. dev_path, dev_buffer,
  509. type, flags, data, binary));
  510. } else {
  511. error = fn_for_each_confined(label, profile,
  512. match_mnt_path_str(subj_cred, profile, path,
  513. buffer, dev_name,
  514. type, flags, data, binary, NULL));
  515. }
  516. out:
  517. aa_put_buffer(buffer);
  518. aa_put_buffer(dev_buffer);
  519. if (dev_path)
  520. path_put(dev_path);
  521. return error;
  522. }
  523. static int profile_umount(const struct cred *subj_cred,
  524. struct aa_profile *profile, const struct path *path,
  525. char *buffer)
  526. {
  527. struct aa_ruleset *rules = list_first_entry(&profile->rules,
  528. typeof(*rules), list);
  529. struct aa_perms perms = { };
  530. const char *name = NULL, *info = NULL;
  531. aa_state_t state;
  532. int error;
  533. AA_BUG(!profile);
  534. AA_BUG(!path);
  535. if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT))
  536. return 0;
  537. error = aa_path_name(path, path_flags(profile, path), buffer, &name,
  538. &info, profile->disconnected);
  539. if (error)
  540. goto audit;
  541. state = aa_dfa_match(rules->policy->dfa,
  542. rules->policy->start[AA_CLASS_MOUNT],
  543. name);
  544. perms = *aa_lookup_perms(rules->policy, state);
  545. if (AA_MAY_UMOUNT & ~perms.allow)
  546. error = -EACCES;
  547. audit:
  548. return audit_mount(subj_cred, profile, OP_UMOUNT, name, NULL, NULL,
  549. NULL, 0, NULL,
  550. AA_MAY_UMOUNT, &perms, info, error);
  551. }
  552. int aa_umount(const struct cred *subj_cred, struct aa_label *label,
  553. struct vfsmount *mnt, int flags)
  554. {
  555. struct aa_profile *profile;
  556. char *buffer = NULL;
  557. int error;
  558. struct path path = { .mnt = mnt, .dentry = mnt->mnt_root };
  559. AA_BUG(!label);
  560. AA_BUG(!mnt);
  561. buffer = aa_get_buffer(false);
  562. if (!buffer)
  563. return -ENOMEM;
  564. error = fn_for_each_confined(label, profile,
  565. profile_umount(subj_cred, profile, &path, buffer));
  566. aa_put_buffer(buffer);
  567. return error;
  568. }
  569. /* helper fn for transition on pivotroot
  570. *
  571. * Returns: label for transition or ERR_PTR. Does not return NULL
  572. */
  573. static struct aa_label *build_pivotroot(const struct cred *subj_cred,
  574. struct aa_profile *profile,
  575. const struct path *new_path,
  576. char *new_buffer,
  577. const struct path *old_path,
  578. char *old_buffer)
  579. {
  580. struct aa_ruleset *rules = list_first_entry(&profile->rules,
  581. typeof(*rules), list);
  582. const char *old_name, *new_name = NULL, *info = NULL;
  583. const char *trans_name = NULL;
  584. struct aa_perms perms = { };
  585. aa_state_t state;
  586. int error;
  587. AA_BUG(!profile);
  588. AA_BUG(!new_path);
  589. AA_BUG(!old_path);
  590. if (profile_unconfined(profile) ||
  591. !RULE_MEDIATES(rules, AA_CLASS_MOUNT))
  592. return aa_get_newest_label(&profile->label);
  593. error = aa_path_name(old_path, path_flags(profile, old_path),
  594. old_buffer, &old_name, &info,
  595. profile->disconnected);
  596. if (error)
  597. goto audit;
  598. error = aa_path_name(new_path, path_flags(profile, new_path),
  599. new_buffer, &new_name, &info,
  600. profile->disconnected);
  601. if (error)
  602. goto audit;
  603. error = -EACCES;
  604. state = aa_dfa_match(rules->policy->dfa,
  605. rules->policy->start[AA_CLASS_MOUNT],
  606. new_name);
  607. state = aa_dfa_null_transition(rules->policy->dfa, state);
  608. state = aa_dfa_match(rules->policy->dfa, state, old_name);
  609. perms = *aa_lookup_perms(rules->policy, state);
  610. if (AA_MAY_PIVOTROOT & perms.allow)
  611. error = 0;
  612. audit:
  613. error = audit_mount(subj_cred, profile, OP_PIVOTROOT, new_name,
  614. old_name,
  615. NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT,
  616. &perms, info, error);
  617. if (error)
  618. return ERR_PTR(error);
  619. return aa_get_newest_label(&profile->label);
  620. }
  621. int aa_pivotroot(const struct cred *subj_cred, struct aa_label *label,
  622. const struct path *old_path,
  623. const struct path *new_path)
  624. {
  625. struct aa_profile *profile;
  626. struct aa_label *target = NULL;
  627. char *old_buffer = NULL, *new_buffer = NULL, *info = NULL;
  628. int error;
  629. AA_BUG(!label);
  630. AA_BUG(!old_path);
  631. AA_BUG(!new_path);
  632. old_buffer = aa_get_buffer(false);
  633. new_buffer = aa_get_buffer(false);
  634. error = -ENOMEM;
  635. if (!old_buffer || !new_buffer)
  636. goto out;
  637. target = fn_label_build(label, profile, GFP_KERNEL,
  638. build_pivotroot(subj_cred, profile, new_path,
  639. new_buffer,
  640. old_path, old_buffer));
  641. if (!target) {
  642. info = "label build failed";
  643. error = -ENOMEM;
  644. goto fail;
  645. } else if (!IS_ERR(target)) {
  646. error = aa_replace_current_label(target);
  647. if (error) {
  648. /* TODO: audit target */
  649. aa_put_label(target);
  650. goto out;
  651. }
  652. aa_put_label(target);
  653. } else
  654. /* already audited error */
  655. error = PTR_ERR(target);
  656. out:
  657. aa_put_buffer(old_buffer);
  658. aa_put_buffer(new_buffer);
  659. return error;
  660. fail:
  661. /* TODO: add back in auditing of new_name and old_name */
  662. error = fn_for_each(label, profile,
  663. audit_mount(subj_cred, profile, OP_PIVOTROOT,
  664. NULL /*new_name */,
  665. NULL /* old_name */,
  666. NULL, NULL,
  667. 0, NULL, AA_MAY_PIVOTROOT, &nullperms, info,
  668. error));
  669. goto out;
  670. }