fs_test.c 110 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Landlock tests - Filesystem
  4. *
  5. * Copyright © 2017-2020 Mickaël Salaün <[email protected]>
  6. * Copyright © 2020 ANSSI
  7. * Copyright © 2020-2022 Microsoft Corporation
  8. */
  9. #define _GNU_SOURCE
  10. #include <fcntl.h>
  11. #include <linux/landlock.h>
  12. #include <sched.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <sys/capability.h>
  16. #include <sys/mount.h>
  17. #include <sys/prctl.h>
  18. #include <sys/sendfile.h>
  19. #include <sys/stat.h>
  20. #include <sys/sysmacros.h>
  21. #include <unistd.h>
  22. #include "common.h"
  23. #ifndef renameat2
  24. int renameat2(int olddirfd, const char *oldpath, int newdirfd,
  25. const char *newpath, unsigned int flags)
  26. {
  27. return syscall(__NR_renameat2, olddirfd, oldpath, newdirfd, newpath,
  28. flags);
  29. }
  30. #endif
  31. #ifndef RENAME_EXCHANGE
  32. #define RENAME_EXCHANGE (1 << 1)
  33. #endif
  34. #define TMP_DIR "tmp"
  35. #define BINARY_PATH "./true"
  36. /* Paths (sibling number and depth) */
  37. static const char dir_s1d1[] = TMP_DIR "/s1d1";
  38. static const char file1_s1d1[] = TMP_DIR "/s1d1/f1";
  39. static const char file2_s1d1[] = TMP_DIR "/s1d1/f2";
  40. static const char dir_s1d2[] = TMP_DIR "/s1d1/s1d2";
  41. static const char file1_s1d2[] = TMP_DIR "/s1d1/s1d2/f1";
  42. static const char file2_s1d2[] = TMP_DIR "/s1d1/s1d2/f2";
  43. static const char dir_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3";
  44. static const char file1_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3/f1";
  45. static const char file2_s1d3[] = TMP_DIR "/s1d1/s1d2/s1d3/f2";
  46. static const char dir_s2d1[] = TMP_DIR "/s2d1";
  47. static const char file1_s2d1[] = TMP_DIR "/s2d1/f1";
  48. static const char dir_s2d2[] = TMP_DIR "/s2d1/s2d2";
  49. static const char file1_s2d2[] = TMP_DIR "/s2d1/s2d2/f1";
  50. static const char dir_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3";
  51. static const char file1_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3/f1";
  52. static const char file2_s2d3[] = TMP_DIR "/s2d1/s2d2/s2d3/f2";
  53. static const char dir_s3d1[] = TMP_DIR "/s3d1";
  54. /* dir_s3d2 is a mount point. */
  55. static const char dir_s3d2[] = TMP_DIR "/s3d1/s3d2";
  56. static const char dir_s3d3[] = TMP_DIR "/s3d1/s3d2/s3d3";
  57. /*
  58. * layout1 hierarchy:
  59. *
  60. * tmp
  61. * ├── s1d1
  62. * │   ├── f1
  63. * │   ├── f2
  64. * │   └── s1d2
  65. * │   ├── f1
  66. * │   ├── f2
  67. * │   └── s1d3
  68. * │   ├── f1
  69. * │   └── f2
  70. * ├── s2d1
  71. * │   ├── f1
  72. * │   └── s2d2
  73. * │   ├── f1
  74. * │   └── s2d3
  75. * │   ├── f1
  76. * │   └── f2
  77. * └── s3d1
  78. * └── s3d2
  79. * └── s3d3
  80. */
  81. static bool fgrep(FILE *const inf, const char *const str)
  82. {
  83. char line[32];
  84. const int slen = strlen(str);
  85. while (!feof(inf)) {
  86. if (!fgets(line, sizeof(line), inf))
  87. break;
  88. if (strncmp(line, str, slen))
  89. continue;
  90. return true;
  91. }
  92. return false;
  93. }
  94. static bool supports_overlayfs(void)
  95. {
  96. bool res;
  97. FILE *const inf = fopen("/proc/filesystems", "r");
  98. /*
  99. * Consider that the filesystem is supported if we cannot get the
  100. * supported ones.
  101. */
  102. if (!inf)
  103. return true;
  104. res = fgrep(inf, "nodev\toverlay\n");
  105. fclose(inf);
  106. return res;
  107. }
  108. static void mkdir_parents(struct __test_metadata *const _metadata,
  109. const char *const path)
  110. {
  111. char *walker;
  112. const char *parent;
  113. int i, err;
  114. ASSERT_NE(path[0], '\0');
  115. walker = strdup(path);
  116. ASSERT_NE(NULL, walker);
  117. parent = walker;
  118. for (i = 1; walker[i]; i++) {
  119. if (walker[i] != '/')
  120. continue;
  121. walker[i] = '\0';
  122. err = mkdir(parent, 0700);
  123. ASSERT_FALSE(err && errno != EEXIST)
  124. {
  125. TH_LOG("Failed to create directory \"%s\": %s", parent,
  126. strerror(errno));
  127. }
  128. walker[i] = '/';
  129. }
  130. free(walker);
  131. }
  132. static void create_directory(struct __test_metadata *const _metadata,
  133. const char *const path)
  134. {
  135. mkdir_parents(_metadata, path);
  136. ASSERT_EQ(0, mkdir(path, 0700))
  137. {
  138. TH_LOG("Failed to create directory \"%s\": %s", path,
  139. strerror(errno));
  140. }
  141. }
  142. static void create_file(struct __test_metadata *const _metadata,
  143. const char *const path)
  144. {
  145. mkdir_parents(_metadata, path);
  146. ASSERT_EQ(0, mknod(path, S_IFREG | 0700, 0))
  147. {
  148. TH_LOG("Failed to create file \"%s\": %s", path,
  149. strerror(errno));
  150. }
  151. }
  152. static int remove_path(const char *const path)
  153. {
  154. char *walker;
  155. int i, ret, err = 0;
  156. walker = strdup(path);
  157. if (!walker) {
  158. err = ENOMEM;
  159. goto out;
  160. }
  161. if (unlink(path) && rmdir(path)) {
  162. if (errno != ENOENT && errno != ENOTDIR)
  163. err = errno;
  164. goto out;
  165. }
  166. for (i = strlen(walker); i > 0; i--) {
  167. if (walker[i] != '/')
  168. continue;
  169. walker[i] = '\0';
  170. ret = rmdir(walker);
  171. if (ret) {
  172. if (errno != ENOTEMPTY && errno != EBUSY)
  173. err = errno;
  174. goto out;
  175. }
  176. if (strcmp(walker, TMP_DIR) == 0)
  177. goto out;
  178. }
  179. out:
  180. free(walker);
  181. return err;
  182. }
  183. static void prepare_layout(struct __test_metadata *const _metadata)
  184. {
  185. disable_caps(_metadata);
  186. umask(0077);
  187. create_directory(_metadata, TMP_DIR);
  188. /*
  189. * Do not pollute the rest of the system: creates a private mount point
  190. * for tests relying on pivot_root(2) and move_mount(2).
  191. */
  192. set_cap(_metadata, CAP_SYS_ADMIN);
  193. ASSERT_EQ(0, unshare(CLONE_NEWNS));
  194. ASSERT_EQ(0, mount("tmp", TMP_DIR, "tmpfs", 0, "size=4m,mode=700"));
  195. ASSERT_EQ(0, mount(NULL, TMP_DIR, NULL, MS_PRIVATE | MS_REC, NULL));
  196. clear_cap(_metadata, CAP_SYS_ADMIN);
  197. }
  198. static void cleanup_layout(struct __test_metadata *const _metadata)
  199. {
  200. set_cap(_metadata, CAP_SYS_ADMIN);
  201. EXPECT_EQ(0, umount(TMP_DIR));
  202. clear_cap(_metadata, CAP_SYS_ADMIN);
  203. EXPECT_EQ(0, remove_path(TMP_DIR));
  204. }
  205. static void create_layout1(struct __test_metadata *const _metadata)
  206. {
  207. create_file(_metadata, file1_s1d1);
  208. create_file(_metadata, file1_s1d2);
  209. create_file(_metadata, file1_s1d3);
  210. create_file(_metadata, file2_s1d1);
  211. create_file(_metadata, file2_s1d2);
  212. create_file(_metadata, file2_s1d3);
  213. create_file(_metadata, file1_s2d1);
  214. create_file(_metadata, file1_s2d2);
  215. create_file(_metadata, file1_s2d3);
  216. create_file(_metadata, file2_s2d3);
  217. create_directory(_metadata, dir_s3d2);
  218. set_cap(_metadata, CAP_SYS_ADMIN);
  219. ASSERT_EQ(0, mount("tmp", dir_s3d2, "tmpfs", 0, "size=4m,mode=700"));
  220. clear_cap(_metadata, CAP_SYS_ADMIN);
  221. ASSERT_EQ(0, mkdir(dir_s3d3, 0700));
  222. }
  223. static void remove_layout1(struct __test_metadata *const _metadata)
  224. {
  225. EXPECT_EQ(0, remove_path(file2_s1d3));
  226. EXPECT_EQ(0, remove_path(file2_s1d2));
  227. EXPECT_EQ(0, remove_path(file2_s1d1));
  228. EXPECT_EQ(0, remove_path(file1_s1d3));
  229. EXPECT_EQ(0, remove_path(file1_s1d2));
  230. EXPECT_EQ(0, remove_path(file1_s1d1));
  231. EXPECT_EQ(0, remove_path(file2_s2d3));
  232. EXPECT_EQ(0, remove_path(file1_s2d3));
  233. EXPECT_EQ(0, remove_path(file1_s2d2));
  234. EXPECT_EQ(0, remove_path(file1_s2d1));
  235. EXPECT_EQ(0, remove_path(dir_s3d3));
  236. set_cap(_metadata, CAP_SYS_ADMIN);
  237. umount(dir_s3d2);
  238. clear_cap(_metadata, CAP_SYS_ADMIN);
  239. EXPECT_EQ(0, remove_path(dir_s3d2));
  240. }
  241. /* clang-format off */
  242. FIXTURE(layout1) {};
  243. /* clang-format on */
  244. FIXTURE_SETUP(layout1)
  245. {
  246. prepare_layout(_metadata);
  247. create_layout1(_metadata);
  248. }
  249. FIXTURE_TEARDOWN(layout1)
  250. {
  251. remove_layout1(_metadata);
  252. cleanup_layout(_metadata);
  253. }
  254. /*
  255. * This helper enables to use the ASSERT_* macros and print the line number
  256. * pointing to the test caller.
  257. */
  258. static int test_open_rel(const int dirfd, const char *const path,
  259. const int flags)
  260. {
  261. int fd;
  262. /* Works with file and directories. */
  263. fd = openat(dirfd, path, flags | O_CLOEXEC);
  264. if (fd < 0)
  265. return errno;
  266. /*
  267. * Mixing error codes from close(2) and open(2) should not lead to any
  268. * (access type) confusion for this test.
  269. */
  270. if (close(fd) != 0)
  271. return errno;
  272. return 0;
  273. }
  274. static int test_open(const char *const path, const int flags)
  275. {
  276. return test_open_rel(AT_FDCWD, path, flags);
  277. }
  278. TEST_F_FORK(layout1, no_restriction)
  279. {
  280. ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
  281. ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
  282. ASSERT_EQ(0, test_open(file2_s1d1, O_RDONLY));
  283. ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
  284. ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
  285. ASSERT_EQ(0, test_open(file2_s1d2, O_RDONLY));
  286. ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
  287. ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
  288. ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY));
  289. ASSERT_EQ(0, test_open(file1_s2d1, O_RDONLY));
  290. ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY));
  291. ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
  292. ASSERT_EQ(0, test_open(dir_s2d3, O_RDONLY));
  293. ASSERT_EQ(0, test_open(file1_s2d3, O_RDONLY));
  294. ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
  295. ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
  296. ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
  297. }
  298. TEST_F_FORK(layout1, inval)
  299. {
  300. struct landlock_path_beneath_attr path_beneath = {
  301. .allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
  302. LANDLOCK_ACCESS_FS_WRITE_FILE,
  303. .parent_fd = -1,
  304. };
  305. struct landlock_ruleset_attr ruleset_attr = {
  306. .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE |
  307. LANDLOCK_ACCESS_FS_WRITE_FILE,
  308. };
  309. int ruleset_fd;
  310. path_beneath.parent_fd =
  311. open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
  312. ASSERT_LE(0, path_beneath.parent_fd);
  313. ruleset_fd = open(dir_s1d1, O_PATH | O_DIRECTORY | O_CLOEXEC);
  314. ASSERT_LE(0, ruleset_fd);
  315. ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
  316. &path_beneath, 0));
  317. /* Returns EBADF because ruleset_fd is not a landlock-ruleset FD. */
  318. ASSERT_EQ(EBADF, errno);
  319. ASSERT_EQ(0, close(ruleset_fd));
  320. ruleset_fd = open(dir_s1d1, O_DIRECTORY | O_CLOEXEC);
  321. ASSERT_LE(0, ruleset_fd);
  322. ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
  323. &path_beneath, 0));
  324. /* Returns EBADFD because ruleset_fd is not a valid ruleset. */
  325. ASSERT_EQ(EBADFD, errno);
  326. ASSERT_EQ(0, close(ruleset_fd));
  327. /* Gets a real ruleset. */
  328. ruleset_fd =
  329. landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
  330. ASSERT_LE(0, ruleset_fd);
  331. ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
  332. &path_beneath, 0));
  333. ASSERT_EQ(0, close(path_beneath.parent_fd));
  334. /* Tests without O_PATH. */
  335. path_beneath.parent_fd = open(dir_s1d2, O_DIRECTORY | O_CLOEXEC);
  336. ASSERT_LE(0, path_beneath.parent_fd);
  337. ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
  338. &path_beneath, 0));
  339. ASSERT_EQ(0, close(path_beneath.parent_fd));
  340. /* Tests with a ruleset FD. */
  341. path_beneath.parent_fd = ruleset_fd;
  342. ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
  343. &path_beneath, 0));
  344. ASSERT_EQ(EBADFD, errno);
  345. /* Checks unhandled allowed_access. */
  346. path_beneath.parent_fd =
  347. open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
  348. ASSERT_LE(0, path_beneath.parent_fd);
  349. /* Test with legitimate values. */
  350. path_beneath.allowed_access |= LANDLOCK_ACCESS_FS_EXECUTE;
  351. ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
  352. &path_beneath, 0));
  353. ASSERT_EQ(EINVAL, errno);
  354. path_beneath.allowed_access &= ~LANDLOCK_ACCESS_FS_EXECUTE;
  355. /* Tests with denied-by-default access right. */
  356. path_beneath.allowed_access |= LANDLOCK_ACCESS_FS_REFER;
  357. ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
  358. &path_beneath, 0));
  359. ASSERT_EQ(EINVAL, errno);
  360. path_beneath.allowed_access &= ~LANDLOCK_ACCESS_FS_REFER;
  361. /* Test with unknown (64-bits) value. */
  362. path_beneath.allowed_access |= (1ULL << 60);
  363. ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
  364. &path_beneath, 0));
  365. ASSERT_EQ(EINVAL, errno);
  366. path_beneath.allowed_access &= ~(1ULL << 60);
  367. /* Test with no access. */
  368. path_beneath.allowed_access = 0;
  369. ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
  370. &path_beneath, 0));
  371. ASSERT_EQ(ENOMSG, errno);
  372. path_beneath.allowed_access &= ~(1ULL << 60);
  373. ASSERT_EQ(0, close(path_beneath.parent_fd));
  374. /* Enforces the ruleset. */
  375. ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
  376. ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
  377. ASSERT_EQ(0, close(ruleset_fd));
  378. }
  379. /* clang-format off */
  380. #define ACCESS_FILE ( \
  381. LANDLOCK_ACCESS_FS_EXECUTE | \
  382. LANDLOCK_ACCESS_FS_WRITE_FILE | \
  383. LANDLOCK_ACCESS_FS_READ_FILE)
  384. #define ACCESS_LAST LANDLOCK_ACCESS_FS_REFER
  385. #define ACCESS_ALL ( \
  386. ACCESS_FILE | \
  387. LANDLOCK_ACCESS_FS_READ_DIR | \
  388. LANDLOCK_ACCESS_FS_REMOVE_DIR | \
  389. LANDLOCK_ACCESS_FS_REMOVE_FILE | \
  390. LANDLOCK_ACCESS_FS_MAKE_CHAR | \
  391. LANDLOCK_ACCESS_FS_MAKE_DIR | \
  392. LANDLOCK_ACCESS_FS_MAKE_REG | \
  393. LANDLOCK_ACCESS_FS_MAKE_SOCK | \
  394. LANDLOCK_ACCESS_FS_MAKE_FIFO | \
  395. LANDLOCK_ACCESS_FS_MAKE_BLOCK | \
  396. LANDLOCK_ACCESS_FS_MAKE_SYM | \
  397. ACCESS_LAST)
  398. /* clang-format on */
  399. TEST_F_FORK(layout1, file_and_dir_access_rights)
  400. {
  401. __u64 access;
  402. int err;
  403. struct landlock_path_beneath_attr path_beneath_file = {},
  404. path_beneath_dir = {};
  405. struct landlock_ruleset_attr ruleset_attr = {
  406. .handled_access_fs = ACCESS_ALL,
  407. };
  408. const int ruleset_fd =
  409. landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
  410. ASSERT_LE(0, ruleset_fd);
  411. /* Tests access rights for files. */
  412. path_beneath_file.parent_fd = open(file1_s1d2, O_PATH | O_CLOEXEC);
  413. ASSERT_LE(0, path_beneath_file.parent_fd);
  414. /* Tests access rights for directories. */
  415. path_beneath_dir.parent_fd =
  416. open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
  417. ASSERT_LE(0, path_beneath_dir.parent_fd);
  418. for (access = 1; access <= ACCESS_LAST; access <<= 1) {
  419. path_beneath_dir.allowed_access = access;
  420. ASSERT_EQ(0, landlock_add_rule(ruleset_fd,
  421. LANDLOCK_RULE_PATH_BENEATH,
  422. &path_beneath_dir, 0));
  423. path_beneath_file.allowed_access = access;
  424. err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
  425. &path_beneath_file, 0);
  426. if (access & ACCESS_FILE) {
  427. ASSERT_EQ(0, err);
  428. } else {
  429. ASSERT_EQ(-1, err);
  430. ASSERT_EQ(EINVAL, errno);
  431. }
  432. }
  433. ASSERT_EQ(0, close(path_beneath_file.parent_fd));
  434. ASSERT_EQ(0, close(path_beneath_dir.parent_fd));
  435. ASSERT_EQ(0, close(ruleset_fd));
  436. }
  437. TEST_F_FORK(layout1, unknown_access_rights)
  438. {
  439. __u64 access_mask;
  440. for (access_mask = 1ULL << 63; access_mask != ACCESS_LAST;
  441. access_mask >>= 1) {
  442. struct landlock_ruleset_attr ruleset_attr = {
  443. .handled_access_fs = access_mask,
  444. };
  445. ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr,
  446. sizeof(ruleset_attr), 0));
  447. ASSERT_EQ(EINVAL, errno);
  448. }
  449. }
  450. static void add_path_beneath(struct __test_metadata *const _metadata,
  451. const int ruleset_fd, const __u64 allowed_access,
  452. const char *const path)
  453. {
  454. struct landlock_path_beneath_attr path_beneath = {
  455. .allowed_access = allowed_access,
  456. };
  457. path_beneath.parent_fd = open(path, O_PATH | O_CLOEXEC);
  458. ASSERT_LE(0, path_beneath.parent_fd)
  459. {
  460. TH_LOG("Failed to open directory \"%s\": %s", path,
  461. strerror(errno));
  462. }
  463. ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
  464. &path_beneath, 0))
  465. {
  466. TH_LOG("Failed to update the ruleset with \"%s\": %s", path,
  467. strerror(errno));
  468. }
  469. ASSERT_EQ(0, close(path_beneath.parent_fd));
  470. }
  471. struct rule {
  472. const char *path;
  473. __u64 access;
  474. };
  475. /* clang-format off */
  476. #define ACCESS_RO ( \
  477. LANDLOCK_ACCESS_FS_READ_FILE | \
  478. LANDLOCK_ACCESS_FS_READ_DIR)
  479. #define ACCESS_RW ( \
  480. ACCESS_RO | \
  481. LANDLOCK_ACCESS_FS_WRITE_FILE)
  482. /* clang-format on */
  483. static int create_ruleset(struct __test_metadata *const _metadata,
  484. const __u64 handled_access_fs,
  485. const struct rule rules[])
  486. {
  487. int ruleset_fd, i;
  488. struct landlock_ruleset_attr ruleset_attr = {
  489. .handled_access_fs = handled_access_fs,
  490. };
  491. ASSERT_NE(NULL, rules)
  492. {
  493. TH_LOG("No rule list");
  494. }
  495. ASSERT_NE(NULL, rules[0].path)
  496. {
  497. TH_LOG("Empty rule list");
  498. }
  499. ruleset_fd =
  500. landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
  501. ASSERT_LE(0, ruleset_fd)
  502. {
  503. TH_LOG("Failed to create a ruleset: %s", strerror(errno));
  504. }
  505. for (i = 0; rules[i].path; i++) {
  506. add_path_beneath(_metadata, ruleset_fd, rules[i].access,
  507. rules[i].path);
  508. }
  509. return ruleset_fd;
  510. }
  511. static void enforce_ruleset(struct __test_metadata *const _metadata,
  512. const int ruleset_fd)
  513. {
  514. ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
  515. ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0))
  516. {
  517. TH_LOG("Failed to enforce ruleset: %s", strerror(errno));
  518. }
  519. }
  520. TEST_F_FORK(layout1, proc_nsfs)
  521. {
  522. const struct rule rules[] = {
  523. {
  524. .path = "/dev/null",
  525. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  526. LANDLOCK_ACCESS_FS_WRITE_FILE,
  527. },
  528. {},
  529. };
  530. struct landlock_path_beneath_attr path_beneath;
  531. const int ruleset_fd = create_ruleset(
  532. _metadata, rules[0].access | LANDLOCK_ACCESS_FS_READ_DIR,
  533. rules);
  534. ASSERT_LE(0, ruleset_fd);
  535. ASSERT_EQ(0, test_open("/proc/self/ns/mnt", O_RDONLY));
  536. enforce_ruleset(_metadata, ruleset_fd);
  537. ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
  538. ASSERT_EQ(EACCES, test_open("/dev", O_RDONLY));
  539. ASSERT_EQ(0, test_open("/dev/null", O_RDONLY));
  540. ASSERT_EQ(EACCES, test_open("/dev/full", O_RDONLY));
  541. ASSERT_EQ(EACCES, test_open("/proc", O_RDONLY));
  542. ASSERT_EQ(EACCES, test_open("/proc/self", O_RDONLY));
  543. ASSERT_EQ(EACCES, test_open("/proc/self/ns", O_RDONLY));
  544. /*
  545. * Because nsfs is an internal filesystem, /proc/self/ns/mnt is a
  546. * disconnected path. Such path cannot be identified and must then be
  547. * allowed.
  548. */
  549. ASSERT_EQ(0, test_open("/proc/self/ns/mnt", O_RDONLY));
  550. /*
  551. * Checks that it is not possible to add nsfs-like filesystem
  552. * references to a ruleset.
  553. */
  554. path_beneath.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
  555. LANDLOCK_ACCESS_FS_WRITE_FILE,
  556. path_beneath.parent_fd = open("/proc/self/ns/mnt", O_PATH | O_CLOEXEC);
  557. ASSERT_LE(0, path_beneath.parent_fd);
  558. ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
  559. &path_beneath, 0));
  560. ASSERT_EQ(EBADFD, errno);
  561. ASSERT_EQ(0, close(path_beneath.parent_fd));
  562. }
  563. TEST_F_FORK(layout1, unpriv)
  564. {
  565. const struct rule rules[] = {
  566. {
  567. .path = dir_s1d2,
  568. .access = ACCESS_RO,
  569. },
  570. {},
  571. };
  572. int ruleset_fd;
  573. drop_caps(_metadata);
  574. ruleset_fd = create_ruleset(_metadata, ACCESS_RO, rules);
  575. ASSERT_LE(0, ruleset_fd);
  576. ASSERT_EQ(-1, landlock_restrict_self(ruleset_fd, 0));
  577. ASSERT_EQ(EPERM, errno);
  578. /* enforce_ruleset() calls prctl(no_new_privs). */
  579. enforce_ruleset(_metadata, ruleset_fd);
  580. ASSERT_EQ(0, close(ruleset_fd));
  581. }
  582. TEST_F_FORK(layout1, effective_access)
  583. {
  584. const struct rule rules[] = {
  585. {
  586. .path = dir_s1d2,
  587. .access = ACCESS_RO,
  588. },
  589. {
  590. .path = file1_s2d2,
  591. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  592. LANDLOCK_ACCESS_FS_WRITE_FILE,
  593. },
  594. {},
  595. };
  596. const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  597. char buf;
  598. int reg_fd;
  599. ASSERT_LE(0, ruleset_fd);
  600. enforce_ruleset(_metadata, ruleset_fd);
  601. ASSERT_EQ(0, close(ruleset_fd));
  602. /* Tests on a directory (with or without O_PATH). */
  603. ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
  604. ASSERT_EQ(0, test_open("/", O_RDONLY | O_PATH));
  605. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
  606. ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY | O_PATH));
  607. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
  608. ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY | O_PATH));
  609. ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
  610. ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
  611. ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
  612. ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
  613. /* Tests on a file (with or without O_PATH). */
  614. ASSERT_EQ(EACCES, test_open(dir_s2d2, O_RDONLY));
  615. ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_PATH));
  616. ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
  617. /* Checks effective read and write actions. */
  618. reg_fd = open(file1_s2d2, O_RDWR | O_CLOEXEC);
  619. ASSERT_LE(0, reg_fd);
  620. ASSERT_EQ(1, write(reg_fd, ".", 1));
  621. ASSERT_LE(0, lseek(reg_fd, 0, SEEK_SET));
  622. ASSERT_EQ(1, read(reg_fd, &buf, 1));
  623. ASSERT_EQ('.', buf);
  624. ASSERT_EQ(0, close(reg_fd));
  625. /* Just in case, double-checks effective actions. */
  626. reg_fd = open(file1_s2d2, O_RDONLY | O_CLOEXEC);
  627. ASSERT_LE(0, reg_fd);
  628. ASSERT_EQ(-1, write(reg_fd, &buf, 1));
  629. ASSERT_EQ(EBADF, errno);
  630. ASSERT_EQ(0, close(reg_fd));
  631. }
  632. TEST_F_FORK(layout1, unhandled_access)
  633. {
  634. const struct rule rules[] = {
  635. {
  636. .path = dir_s1d2,
  637. .access = ACCESS_RO,
  638. },
  639. {},
  640. };
  641. /* Here, we only handle read accesses, not write accesses. */
  642. const int ruleset_fd = create_ruleset(_metadata, ACCESS_RO, rules);
  643. ASSERT_LE(0, ruleset_fd);
  644. enforce_ruleset(_metadata, ruleset_fd);
  645. ASSERT_EQ(0, close(ruleset_fd));
  646. /*
  647. * Because the policy does not handle LANDLOCK_ACCESS_FS_WRITE_FILE,
  648. * opening for write-only should be allowed, but not read-write.
  649. */
  650. ASSERT_EQ(0, test_open(file1_s1d1, O_WRONLY));
  651. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
  652. ASSERT_EQ(0, test_open(file1_s1d2, O_WRONLY));
  653. ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
  654. }
  655. TEST_F_FORK(layout1, ruleset_overlap)
  656. {
  657. const struct rule rules[] = {
  658. /* These rules should be ORed among them. */
  659. {
  660. .path = dir_s1d2,
  661. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  662. LANDLOCK_ACCESS_FS_WRITE_FILE,
  663. },
  664. {
  665. .path = dir_s1d2,
  666. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  667. LANDLOCK_ACCESS_FS_READ_DIR,
  668. },
  669. {},
  670. };
  671. const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  672. ASSERT_LE(0, ruleset_fd);
  673. enforce_ruleset(_metadata, ruleset_fd);
  674. ASSERT_EQ(0, close(ruleset_fd));
  675. /* Checks s1d1 hierarchy. */
  676. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
  677. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
  678. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
  679. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  680. /* Checks s1d2 hierarchy. */
  681. ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
  682. ASSERT_EQ(0, test_open(file1_s1d2, O_WRONLY));
  683. ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
  684. ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
  685. /* Checks s1d3 hierarchy. */
  686. ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
  687. ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
  688. ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
  689. ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
  690. }
  691. TEST_F_FORK(layout1, layer_rule_unions)
  692. {
  693. const struct rule layer1[] = {
  694. {
  695. .path = dir_s1d2,
  696. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  697. },
  698. /* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
  699. {
  700. .path = dir_s1d3,
  701. .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
  702. },
  703. {},
  704. };
  705. const struct rule layer2[] = {
  706. /* Doesn't change anything from layer1. */
  707. {
  708. .path = dir_s1d2,
  709. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  710. LANDLOCK_ACCESS_FS_WRITE_FILE,
  711. },
  712. {},
  713. };
  714. const struct rule layer3[] = {
  715. /* Only allows write (but not read) to dir_s1d3. */
  716. {
  717. .path = dir_s1d2,
  718. .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
  719. },
  720. {},
  721. };
  722. int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1);
  723. ASSERT_LE(0, ruleset_fd);
  724. enforce_ruleset(_metadata, ruleset_fd);
  725. ASSERT_EQ(0, close(ruleset_fd));
  726. /* Checks s1d1 hierarchy with layer1. */
  727. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
  728. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
  729. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
  730. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  731. /* Checks s1d2 hierarchy with layer1. */
  732. ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
  733. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
  734. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
  735. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  736. /* Checks s1d3 hierarchy with layer1. */
  737. ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
  738. ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
  739. /* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
  740. ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
  741. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  742. /* Doesn't change anything from layer1. */
  743. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2);
  744. ASSERT_LE(0, ruleset_fd);
  745. enforce_ruleset(_metadata, ruleset_fd);
  746. ASSERT_EQ(0, close(ruleset_fd));
  747. /* Checks s1d1 hierarchy with layer2. */
  748. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
  749. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
  750. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
  751. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  752. /* Checks s1d2 hierarchy with layer2. */
  753. ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
  754. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
  755. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
  756. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  757. /* Checks s1d3 hierarchy with layer2. */
  758. ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
  759. ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
  760. /* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
  761. ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
  762. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  763. /* Only allows write (but not read) to dir_s1d3. */
  764. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3);
  765. ASSERT_LE(0, ruleset_fd);
  766. enforce_ruleset(_metadata, ruleset_fd);
  767. ASSERT_EQ(0, close(ruleset_fd));
  768. /* Checks s1d1 hierarchy with layer3. */
  769. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
  770. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
  771. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
  772. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  773. /* Checks s1d2 hierarchy with layer3. */
  774. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDONLY));
  775. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
  776. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
  777. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  778. /* Checks s1d3 hierarchy with layer3. */
  779. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
  780. ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
  781. /* dir_s1d3 should now deny READ_FILE and WRITE_FILE (O_RDWR). */
  782. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDWR));
  783. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  784. }
  785. TEST_F_FORK(layout1, non_overlapping_accesses)
  786. {
  787. const struct rule layer1[] = {
  788. {
  789. .path = dir_s1d2,
  790. .access = LANDLOCK_ACCESS_FS_MAKE_REG,
  791. },
  792. {},
  793. };
  794. const struct rule layer2[] = {
  795. {
  796. .path = dir_s1d3,
  797. .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
  798. },
  799. {},
  800. };
  801. int ruleset_fd;
  802. ASSERT_EQ(0, unlink(file1_s1d1));
  803. ASSERT_EQ(0, unlink(file1_s1d2));
  804. ruleset_fd =
  805. create_ruleset(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, layer1);
  806. ASSERT_LE(0, ruleset_fd);
  807. enforce_ruleset(_metadata, ruleset_fd);
  808. ASSERT_EQ(0, close(ruleset_fd));
  809. ASSERT_EQ(-1, mknod(file1_s1d1, S_IFREG | 0700, 0));
  810. ASSERT_EQ(EACCES, errno);
  811. ASSERT_EQ(0, mknod(file1_s1d2, S_IFREG | 0700, 0));
  812. ASSERT_EQ(0, unlink(file1_s1d2));
  813. ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_REMOVE_FILE,
  814. layer2);
  815. ASSERT_LE(0, ruleset_fd);
  816. enforce_ruleset(_metadata, ruleset_fd);
  817. ASSERT_EQ(0, close(ruleset_fd));
  818. /* Unchanged accesses for file creation. */
  819. ASSERT_EQ(-1, mknod(file1_s1d1, S_IFREG | 0700, 0));
  820. ASSERT_EQ(EACCES, errno);
  821. ASSERT_EQ(0, mknod(file1_s1d2, S_IFREG | 0700, 0));
  822. /* Checks file removing. */
  823. ASSERT_EQ(-1, unlink(file1_s1d2));
  824. ASSERT_EQ(EACCES, errno);
  825. ASSERT_EQ(0, unlink(file1_s1d3));
  826. }
  827. TEST_F_FORK(layout1, interleaved_masked_accesses)
  828. {
  829. /*
  830. * Checks overly restrictive rules:
  831. * layer 1: allows R s1d1/s1d2/s1d3/file1
  832. * layer 2: allows RW s1d1/s1d2/s1d3
  833. * allows W s1d1/s1d2
  834. * denies R s1d1/s1d2
  835. * layer 3: allows R s1d1
  836. * layer 4: allows R s1d1/s1d2
  837. * denies W s1d1/s1d2
  838. * layer 5: allows R s1d1/s1d2
  839. * layer 6: allows X ----
  840. * layer 7: allows W s1d1/s1d2
  841. * denies R s1d1/s1d2
  842. */
  843. const struct rule layer1_read[] = {
  844. /* Allows read access to file1_s1d3 with the first layer. */
  845. {
  846. .path = file1_s1d3,
  847. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  848. },
  849. {},
  850. };
  851. /* First rule with write restrictions. */
  852. const struct rule layer2_read_write[] = {
  853. /* Start by granting read-write access via its parent directory... */
  854. {
  855. .path = dir_s1d3,
  856. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  857. LANDLOCK_ACCESS_FS_WRITE_FILE,
  858. },
  859. /* ...but also denies read access via its grandparent directory. */
  860. {
  861. .path = dir_s1d2,
  862. .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
  863. },
  864. {},
  865. };
  866. const struct rule layer3_read[] = {
  867. /* Allows read access via its great-grandparent directory. */
  868. {
  869. .path = dir_s1d1,
  870. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  871. },
  872. {},
  873. };
  874. const struct rule layer4_read_write[] = {
  875. /*
  876. * Try to confuse the deny access by denying write (but not
  877. * read) access via its grandparent directory.
  878. */
  879. {
  880. .path = dir_s1d2,
  881. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  882. },
  883. {},
  884. };
  885. const struct rule layer5_read[] = {
  886. /*
  887. * Try to override layer2's deny read access by explicitly
  888. * allowing read access via file1_s1d3's grandparent.
  889. */
  890. {
  891. .path = dir_s1d2,
  892. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  893. },
  894. {},
  895. };
  896. const struct rule layer6_execute[] = {
  897. /*
  898. * Restricts an unrelated file hierarchy with a new access
  899. * (non-overlapping) type.
  900. */
  901. {
  902. .path = dir_s2d1,
  903. .access = LANDLOCK_ACCESS_FS_EXECUTE,
  904. },
  905. {},
  906. };
  907. const struct rule layer7_read_write[] = {
  908. /*
  909. * Finally, denies read access to file1_s1d3 via its
  910. * grandparent.
  911. */
  912. {
  913. .path = dir_s1d2,
  914. .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
  915. },
  916. {},
  917. };
  918. int ruleset_fd;
  919. ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
  920. layer1_read);
  921. ASSERT_LE(0, ruleset_fd);
  922. enforce_ruleset(_metadata, ruleset_fd);
  923. ASSERT_EQ(0, close(ruleset_fd));
  924. /* Checks that read access is granted for file1_s1d3 with layer 1. */
  925. ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
  926. ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
  927. ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
  928. ruleset_fd = create_ruleset(_metadata,
  929. LANDLOCK_ACCESS_FS_READ_FILE |
  930. LANDLOCK_ACCESS_FS_WRITE_FILE,
  931. layer2_read_write);
  932. ASSERT_LE(0, ruleset_fd);
  933. enforce_ruleset(_metadata, ruleset_fd);
  934. ASSERT_EQ(0, close(ruleset_fd));
  935. /* Checks that previous access rights are unchanged with layer 2. */
  936. ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
  937. ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
  938. ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
  939. ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
  940. layer3_read);
  941. ASSERT_LE(0, ruleset_fd);
  942. enforce_ruleset(_metadata, ruleset_fd);
  943. ASSERT_EQ(0, close(ruleset_fd));
  944. /* Checks that previous access rights are unchanged with layer 3. */
  945. ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
  946. ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
  947. ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
  948. /* This time, denies write access for the file hierarchy. */
  949. ruleset_fd = create_ruleset(_metadata,
  950. LANDLOCK_ACCESS_FS_READ_FILE |
  951. LANDLOCK_ACCESS_FS_WRITE_FILE,
  952. layer4_read_write);
  953. ASSERT_LE(0, ruleset_fd);
  954. enforce_ruleset(_metadata, ruleset_fd);
  955. ASSERT_EQ(0, close(ruleset_fd));
  956. /*
  957. * Checks that the only change with layer 4 is that write access is
  958. * denied.
  959. */
  960. ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
  961. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
  962. ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
  963. ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
  964. ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
  965. layer5_read);
  966. ASSERT_LE(0, ruleset_fd);
  967. enforce_ruleset(_metadata, ruleset_fd);
  968. ASSERT_EQ(0, close(ruleset_fd));
  969. /* Checks that previous access rights are unchanged with layer 5. */
  970. ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
  971. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
  972. ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
  973. ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
  974. ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_EXECUTE,
  975. layer6_execute);
  976. ASSERT_LE(0, ruleset_fd);
  977. enforce_ruleset(_metadata, ruleset_fd);
  978. ASSERT_EQ(0, close(ruleset_fd));
  979. /* Checks that previous access rights are unchanged with layer 6. */
  980. ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
  981. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
  982. ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
  983. ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
  984. ruleset_fd = create_ruleset(_metadata,
  985. LANDLOCK_ACCESS_FS_READ_FILE |
  986. LANDLOCK_ACCESS_FS_WRITE_FILE,
  987. layer7_read_write);
  988. ASSERT_LE(0, ruleset_fd);
  989. enforce_ruleset(_metadata, ruleset_fd);
  990. ASSERT_EQ(0, close(ruleset_fd));
  991. /* Checks read access is now denied with layer 7. */
  992. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
  993. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
  994. ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
  995. ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
  996. }
  997. TEST_F_FORK(layout1, inherit_subset)
  998. {
  999. const struct rule rules[] = {
  1000. {
  1001. .path = dir_s1d2,
  1002. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  1003. LANDLOCK_ACCESS_FS_READ_DIR,
  1004. },
  1005. {},
  1006. };
  1007. const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  1008. ASSERT_LE(0, ruleset_fd);
  1009. enforce_ruleset(_metadata, ruleset_fd);
  1010. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
  1011. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  1012. /* Write access is forbidden. */
  1013. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
  1014. /* Readdir access is allowed. */
  1015. ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
  1016. /* Write access is forbidden. */
  1017. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
  1018. /* Readdir access is allowed. */
  1019. ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
  1020. /*
  1021. * Tests shared rule extension: the following rules should not grant
  1022. * any new access, only remove some. Once enforced, these rules are
  1023. * ANDed with the previous ones.
  1024. */
  1025. add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
  1026. dir_s1d2);
  1027. /*
  1028. * According to ruleset_fd, dir_s1d2 should now have the
  1029. * LANDLOCK_ACCESS_FS_READ_FILE and LANDLOCK_ACCESS_FS_WRITE_FILE
  1030. * access rights (even if this directory is opened a second time).
  1031. * However, when enforcing this updated ruleset, the ruleset tied to
  1032. * the current process (i.e. its domain) will still only have the
  1033. * dir_s1d2 with LANDLOCK_ACCESS_FS_READ_FILE and
  1034. * LANDLOCK_ACCESS_FS_READ_DIR accesses, but
  1035. * LANDLOCK_ACCESS_FS_WRITE_FILE must not be allowed because it would
  1036. * be a privilege escalation.
  1037. */
  1038. enforce_ruleset(_metadata, ruleset_fd);
  1039. /* Same tests and results as above. */
  1040. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
  1041. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  1042. /* It is still forbidden to write in file1_s1d2. */
  1043. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
  1044. /* Readdir access is still allowed. */
  1045. ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
  1046. /* It is still forbidden to write in file1_s1d3. */
  1047. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
  1048. /* Readdir access is still allowed. */
  1049. ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
  1050. /*
  1051. * Try to get more privileges by adding new access rights to the parent
  1052. * directory: dir_s1d1.
  1053. */
  1054. add_path_beneath(_metadata, ruleset_fd, ACCESS_RW, dir_s1d1);
  1055. enforce_ruleset(_metadata, ruleset_fd);
  1056. /* Same tests and results as above. */
  1057. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
  1058. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  1059. /* It is still forbidden to write in file1_s1d2. */
  1060. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
  1061. /* Readdir access is still allowed. */
  1062. ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
  1063. /* It is still forbidden to write in file1_s1d3. */
  1064. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
  1065. /* Readdir access is still allowed. */
  1066. ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
  1067. /*
  1068. * Now, dir_s1d3 get a new rule tied to it, only allowing
  1069. * LANDLOCK_ACCESS_FS_WRITE_FILE. The (kernel internal) difference is
  1070. * that there was no rule tied to it before.
  1071. */
  1072. add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
  1073. dir_s1d3);
  1074. enforce_ruleset(_metadata, ruleset_fd);
  1075. ASSERT_EQ(0, close(ruleset_fd));
  1076. /*
  1077. * Same tests and results as above, except for open(dir_s1d3) which is
  1078. * now denied because the new rule mask the rule previously inherited
  1079. * from dir_s1d2.
  1080. */
  1081. /* Same tests and results as above. */
  1082. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
  1083. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  1084. /* It is still forbidden to write in file1_s1d2. */
  1085. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
  1086. /* Readdir access is still allowed. */
  1087. ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
  1088. /* It is still forbidden to write in file1_s1d3. */
  1089. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
  1090. /*
  1091. * Readdir of dir_s1d3 is still allowed because of the OR policy inside
  1092. * the same layer.
  1093. */
  1094. ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
  1095. }
  1096. TEST_F_FORK(layout1, inherit_superset)
  1097. {
  1098. const struct rule rules[] = {
  1099. {
  1100. .path = dir_s1d3,
  1101. .access = ACCESS_RO,
  1102. },
  1103. {},
  1104. };
  1105. const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  1106. ASSERT_LE(0, ruleset_fd);
  1107. enforce_ruleset(_metadata, ruleset_fd);
  1108. /* Readdir access is denied for dir_s1d2. */
  1109. ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
  1110. /* Readdir access is allowed for dir_s1d3. */
  1111. ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
  1112. /* File access is allowed for file1_s1d3. */
  1113. ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
  1114. /* Now dir_s1d2, parent of dir_s1d3, gets a new rule tied to it. */
  1115. add_path_beneath(_metadata, ruleset_fd,
  1116. LANDLOCK_ACCESS_FS_READ_FILE |
  1117. LANDLOCK_ACCESS_FS_READ_DIR,
  1118. dir_s1d2);
  1119. enforce_ruleset(_metadata, ruleset_fd);
  1120. ASSERT_EQ(0, close(ruleset_fd));
  1121. /* Readdir access is still denied for dir_s1d2. */
  1122. ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
  1123. /* Readdir access is still allowed for dir_s1d3. */
  1124. ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
  1125. /* File access is still allowed for file1_s1d3. */
  1126. ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
  1127. }
  1128. TEST_F_FORK(layout1, max_layers)
  1129. {
  1130. int i, err;
  1131. const struct rule rules[] = {
  1132. {
  1133. .path = dir_s1d2,
  1134. .access = ACCESS_RO,
  1135. },
  1136. {},
  1137. };
  1138. const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  1139. ASSERT_LE(0, ruleset_fd);
  1140. for (i = 0; i < 16; i++)
  1141. enforce_ruleset(_metadata, ruleset_fd);
  1142. for (i = 0; i < 2; i++) {
  1143. err = landlock_restrict_self(ruleset_fd, 0);
  1144. ASSERT_EQ(-1, err);
  1145. ASSERT_EQ(E2BIG, errno);
  1146. }
  1147. ASSERT_EQ(0, close(ruleset_fd));
  1148. }
  1149. TEST_F_FORK(layout1, empty_or_same_ruleset)
  1150. {
  1151. struct landlock_ruleset_attr ruleset_attr = {};
  1152. int ruleset_fd;
  1153. /* Tests empty handled_access_fs. */
  1154. ruleset_fd =
  1155. landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
  1156. ASSERT_LE(-1, ruleset_fd);
  1157. ASSERT_EQ(ENOMSG, errno);
  1158. /* Enforces policy which deny read access to all files. */
  1159. ruleset_attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE;
  1160. ruleset_fd =
  1161. landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
  1162. ASSERT_LE(0, ruleset_fd);
  1163. enforce_ruleset(_metadata, ruleset_fd);
  1164. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
  1165. ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
  1166. /* Nests a policy which deny read access to all directories. */
  1167. ruleset_attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR;
  1168. ruleset_fd =
  1169. landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
  1170. ASSERT_LE(0, ruleset_fd);
  1171. enforce_ruleset(_metadata, ruleset_fd);
  1172. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
  1173. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
  1174. /* Enforces a second time with the same ruleset. */
  1175. enforce_ruleset(_metadata, ruleset_fd);
  1176. ASSERT_EQ(0, close(ruleset_fd));
  1177. }
  1178. TEST_F_FORK(layout1, rule_on_mountpoint)
  1179. {
  1180. const struct rule rules[] = {
  1181. {
  1182. .path = dir_s1d1,
  1183. .access = ACCESS_RO,
  1184. },
  1185. {
  1186. /* dir_s3d2 is a mount point. */
  1187. .path = dir_s3d2,
  1188. .access = ACCESS_RO,
  1189. },
  1190. {},
  1191. };
  1192. const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  1193. ASSERT_LE(0, ruleset_fd);
  1194. enforce_ruleset(_metadata, ruleset_fd);
  1195. ASSERT_EQ(0, close(ruleset_fd));
  1196. ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
  1197. ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY));
  1198. ASSERT_EQ(EACCES, test_open(dir_s3d1, O_RDONLY));
  1199. ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
  1200. ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
  1201. }
  1202. TEST_F_FORK(layout1, rule_over_mountpoint)
  1203. {
  1204. const struct rule rules[] = {
  1205. {
  1206. .path = dir_s1d1,
  1207. .access = ACCESS_RO,
  1208. },
  1209. {
  1210. /* dir_s3d2 is a mount point. */
  1211. .path = dir_s3d1,
  1212. .access = ACCESS_RO,
  1213. },
  1214. {},
  1215. };
  1216. const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  1217. ASSERT_LE(0, ruleset_fd);
  1218. enforce_ruleset(_metadata, ruleset_fd);
  1219. ASSERT_EQ(0, close(ruleset_fd));
  1220. ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
  1221. ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY));
  1222. ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
  1223. ASSERT_EQ(0, test_open(dir_s3d2, O_RDONLY));
  1224. ASSERT_EQ(0, test_open(dir_s3d3, O_RDONLY));
  1225. }
  1226. /*
  1227. * This test verifies that we can apply a landlock rule on the root directory
  1228. * (which might require special handling).
  1229. */
  1230. TEST_F_FORK(layout1, rule_over_root_allow_then_deny)
  1231. {
  1232. struct rule rules[] = {
  1233. {
  1234. .path = "/",
  1235. .access = ACCESS_RO,
  1236. },
  1237. {},
  1238. };
  1239. int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  1240. ASSERT_LE(0, ruleset_fd);
  1241. enforce_ruleset(_metadata, ruleset_fd);
  1242. ASSERT_EQ(0, close(ruleset_fd));
  1243. /* Checks allowed access. */
  1244. ASSERT_EQ(0, test_open("/", O_RDONLY));
  1245. ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
  1246. rules[0].access = LANDLOCK_ACCESS_FS_READ_FILE;
  1247. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  1248. ASSERT_LE(0, ruleset_fd);
  1249. enforce_ruleset(_metadata, ruleset_fd);
  1250. ASSERT_EQ(0, close(ruleset_fd));
  1251. /* Checks denied access (on a directory). */
  1252. ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
  1253. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
  1254. }
  1255. TEST_F_FORK(layout1, rule_over_root_deny)
  1256. {
  1257. const struct rule rules[] = {
  1258. {
  1259. .path = "/",
  1260. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  1261. },
  1262. {},
  1263. };
  1264. const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  1265. ASSERT_LE(0, ruleset_fd);
  1266. enforce_ruleset(_metadata, ruleset_fd);
  1267. ASSERT_EQ(0, close(ruleset_fd));
  1268. /* Checks denied access (on a directory). */
  1269. ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
  1270. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
  1271. }
  1272. TEST_F_FORK(layout1, rule_inside_mount_ns)
  1273. {
  1274. const struct rule rules[] = {
  1275. {
  1276. .path = "s3d3",
  1277. .access = ACCESS_RO,
  1278. },
  1279. {},
  1280. };
  1281. int ruleset_fd;
  1282. set_cap(_metadata, CAP_SYS_ADMIN);
  1283. ASSERT_EQ(0, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3))
  1284. {
  1285. TH_LOG("Failed to pivot root: %s", strerror(errno));
  1286. };
  1287. ASSERT_EQ(0, chdir("/"));
  1288. clear_cap(_metadata, CAP_SYS_ADMIN);
  1289. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  1290. ASSERT_LE(0, ruleset_fd);
  1291. enforce_ruleset(_metadata, ruleset_fd);
  1292. ASSERT_EQ(0, close(ruleset_fd));
  1293. ASSERT_EQ(0, test_open("s3d3", O_RDONLY));
  1294. ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
  1295. }
  1296. TEST_F_FORK(layout1, mount_and_pivot)
  1297. {
  1298. const struct rule rules[] = {
  1299. {
  1300. .path = dir_s3d2,
  1301. .access = ACCESS_RO,
  1302. },
  1303. {},
  1304. };
  1305. const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  1306. ASSERT_LE(0, ruleset_fd);
  1307. enforce_ruleset(_metadata, ruleset_fd);
  1308. ASSERT_EQ(0, close(ruleset_fd));
  1309. set_cap(_metadata, CAP_SYS_ADMIN);
  1310. ASSERT_EQ(-1, mount(NULL, dir_s3d2, NULL, MS_RDONLY, NULL));
  1311. ASSERT_EQ(EPERM, errno);
  1312. ASSERT_EQ(-1, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3));
  1313. ASSERT_EQ(EPERM, errno);
  1314. clear_cap(_metadata, CAP_SYS_ADMIN);
  1315. }
  1316. TEST_F_FORK(layout1, move_mount)
  1317. {
  1318. const struct rule rules[] = {
  1319. {
  1320. .path = dir_s3d2,
  1321. .access = ACCESS_RO,
  1322. },
  1323. {},
  1324. };
  1325. const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  1326. ASSERT_LE(0, ruleset_fd);
  1327. set_cap(_metadata, CAP_SYS_ADMIN);
  1328. ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
  1329. dir_s1d2, 0))
  1330. {
  1331. TH_LOG("Failed to move mount: %s", strerror(errno));
  1332. }
  1333. ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s1d2, AT_FDCWD,
  1334. dir_s3d2, 0));
  1335. clear_cap(_metadata, CAP_SYS_ADMIN);
  1336. enforce_ruleset(_metadata, ruleset_fd);
  1337. ASSERT_EQ(0, close(ruleset_fd));
  1338. set_cap(_metadata, CAP_SYS_ADMIN);
  1339. ASSERT_EQ(-1, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
  1340. dir_s1d2, 0));
  1341. ASSERT_EQ(EPERM, errno);
  1342. clear_cap(_metadata, CAP_SYS_ADMIN);
  1343. }
  1344. TEST_F_FORK(layout1, release_inodes)
  1345. {
  1346. const struct rule rules[] = {
  1347. {
  1348. .path = dir_s1d1,
  1349. .access = ACCESS_RO,
  1350. },
  1351. {
  1352. .path = dir_s3d2,
  1353. .access = ACCESS_RO,
  1354. },
  1355. {
  1356. .path = dir_s3d3,
  1357. .access = ACCESS_RO,
  1358. },
  1359. {},
  1360. };
  1361. const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
  1362. ASSERT_LE(0, ruleset_fd);
  1363. /* Unmount a file hierarchy while it is being used by a ruleset. */
  1364. set_cap(_metadata, CAP_SYS_ADMIN);
  1365. ASSERT_EQ(0, umount(dir_s3d2));
  1366. clear_cap(_metadata, CAP_SYS_ADMIN);
  1367. enforce_ruleset(_metadata, ruleset_fd);
  1368. ASSERT_EQ(0, close(ruleset_fd));
  1369. ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
  1370. ASSERT_EQ(EACCES, test_open(dir_s3d2, O_RDONLY));
  1371. /* This dir_s3d3 would not be allowed and does not exist anyway. */
  1372. ASSERT_EQ(ENOENT, test_open(dir_s3d3, O_RDONLY));
  1373. }
  1374. enum relative_access {
  1375. REL_OPEN,
  1376. REL_CHDIR,
  1377. REL_CHROOT_ONLY,
  1378. REL_CHROOT_CHDIR,
  1379. };
  1380. static void test_relative_path(struct __test_metadata *const _metadata,
  1381. const enum relative_access rel)
  1382. {
  1383. /*
  1384. * Common layer to check that chroot doesn't ignore it (i.e. a chroot
  1385. * is not a disconnected root directory).
  1386. */
  1387. const struct rule layer1_base[] = {
  1388. {
  1389. .path = TMP_DIR,
  1390. .access = ACCESS_RO,
  1391. },
  1392. {},
  1393. };
  1394. const struct rule layer2_subs[] = {
  1395. {
  1396. .path = dir_s1d2,
  1397. .access = ACCESS_RO,
  1398. },
  1399. {
  1400. .path = dir_s2d2,
  1401. .access = ACCESS_RO,
  1402. },
  1403. {},
  1404. };
  1405. int dirfd, ruleset_fd;
  1406. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_base);
  1407. ASSERT_LE(0, ruleset_fd);
  1408. enforce_ruleset(_metadata, ruleset_fd);
  1409. ASSERT_EQ(0, close(ruleset_fd));
  1410. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_subs);
  1411. ASSERT_LE(0, ruleset_fd);
  1412. switch (rel) {
  1413. case REL_OPEN:
  1414. case REL_CHDIR:
  1415. break;
  1416. case REL_CHROOT_ONLY:
  1417. ASSERT_EQ(0, chdir(dir_s2d2));
  1418. break;
  1419. case REL_CHROOT_CHDIR:
  1420. ASSERT_EQ(0, chdir(dir_s1d2));
  1421. break;
  1422. default:
  1423. ASSERT_TRUE(false);
  1424. return;
  1425. }
  1426. set_cap(_metadata, CAP_SYS_CHROOT);
  1427. enforce_ruleset(_metadata, ruleset_fd);
  1428. switch (rel) {
  1429. case REL_OPEN:
  1430. dirfd = open(dir_s1d2, O_DIRECTORY);
  1431. ASSERT_LE(0, dirfd);
  1432. break;
  1433. case REL_CHDIR:
  1434. ASSERT_EQ(0, chdir(dir_s1d2));
  1435. dirfd = AT_FDCWD;
  1436. break;
  1437. case REL_CHROOT_ONLY:
  1438. /* Do chroot into dir_s1d2 (relative to dir_s2d2). */
  1439. ASSERT_EQ(0, chroot("../../s1d1/s1d2"))
  1440. {
  1441. TH_LOG("Failed to chroot: %s", strerror(errno));
  1442. }
  1443. dirfd = AT_FDCWD;
  1444. break;
  1445. case REL_CHROOT_CHDIR:
  1446. /* Do chroot into dir_s1d2. */
  1447. ASSERT_EQ(0, chroot("."))
  1448. {
  1449. TH_LOG("Failed to chroot: %s", strerror(errno));
  1450. }
  1451. dirfd = AT_FDCWD;
  1452. break;
  1453. }
  1454. ASSERT_EQ((rel == REL_CHROOT_CHDIR) ? 0 : EACCES,
  1455. test_open_rel(dirfd, "..", O_RDONLY));
  1456. ASSERT_EQ(0, test_open_rel(dirfd, ".", O_RDONLY));
  1457. if (rel == REL_CHROOT_ONLY) {
  1458. /* The current directory is dir_s2d2. */
  1459. ASSERT_EQ(0, test_open_rel(dirfd, "./s2d3", O_RDONLY));
  1460. } else {
  1461. /* The current directory is dir_s1d2. */
  1462. ASSERT_EQ(0, test_open_rel(dirfd, "./s1d3", O_RDONLY));
  1463. }
  1464. if (rel == REL_CHROOT_ONLY || rel == REL_CHROOT_CHDIR) {
  1465. /* Checks the root dir_s1d2. */
  1466. ASSERT_EQ(0, test_open_rel(dirfd, "/..", O_RDONLY));
  1467. ASSERT_EQ(0, test_open_rel(dirfd, "/", O_RDONLY));
  1468. ASSERT_EQ(0, test_open_rel(dirfd, "/f1", O_RDONLY));
  1469. ASSERT_EQ(0, test_open_rel(dirfd, "/s1d3", O_RDONLY));
  1470. }
  1471. if (rel != REL_CHROOT_CHDIR) {
  1472. ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s1d1", O_RDONLY));
  1473. ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2", O_RDONLY));
  1474. ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2/s1d3",
  1475. O_RDONLY));
  1476. ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s2d1", O_RDONLY));
  1477. ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2", O_RDONLY));
  1478. ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2/s2d3",
  1479. O_RDONLY));
  1480. }
  1481. if (rel == REL_OPEN)
  1482. ASSERT_EQ(0, close(dirfd));
  1483. ASSERT_EQ(0, close(ruleset_fd));
  1484. }
  1485. TEST_F_FORK(layout1, relative_open)
  1486. {
  1487. test_relative_path(_metadata, REL_OPEN);
  1488. }
  1489. TEST_F_FORK(layout1, relative_chdir)
  1490. {
  1491. test_relative_path(_metadata, REL_CHDIR);
  1492. }
  1493. TEST_F_FORK(layout1, relative_chroot_only)
  1494. {
  1495. test_relative_path(_metadata, REL_CHROOT_ONLY);
  1496. }
  1497. TEST_F_FORK(layout1, relative_chroot_chdir)
  1498. {
  1499. test_relative_path(_metadata, REL_CHROOT_CHDIR);
  1500. }
  1501. static void copy_binary(struct __test_metadata *const _metadata,
  1502. const char *const dst_path)
  1503. {
  1504. int dst_fd, src_fd;
  1505. struct stat statbuf;
  1506. dst_fd = open(dst_path, O_WRONLY | O_TRUNC | O_CLOEXEC);
  1507. ASSERT_LE(0, dst_fd)
  1508. {
  1509. TH_LOG("Failed to open \"%s\": %s", dst_path, strerror(errno));
  1510. }
  1511. src_fd = open(BINARY_PATH, O_RDONLY | O_CLOEXEC);
  1512. ASSERT_LE(0, src_fd)
  1513. {
  1514. TH_LOG("Failed to open \"" BINARY_PATH "\": %s",
  1515. strerror(errno));
  1516. }
  1517. ASSERT_EQ(0, fstat(src_fd, &statbuf));
  1518. ASSERT_EQ(statbuf.st_size,
  1519. sendfile(dst_fd, src_fd, 0, statbuf.st_size));
  1520. ASSERT_EQ(0, close(src_fd));
  1521. ASSERT_EQ(0, close(dst_fd));
  1522. }
  1523. static void test_execute(struct __test_metadata *const _metadata, const int err,
  1524. const char *const path)
  1525. {
  1526. int status;
  1527. char *const argv[] = { (char *)path, NULL };
  1528. const pid_t child = fork();
  1529. ASSERT_LE(0, child);
  1530. if (child == 0) {
  1531. ASSERT_EQ(err ? -1 : 0, execve(path, argv, NULL))
  1532. {
  1533. TH_LOG("Failed to execute \"%s\": %s", path,
  1534. strerror(errno));
  1535. };
  1536. ASSERT_EQ(err, errno);
  1537. _exit(_metadata->passed ? 2 : 1);
  1538. return;
  1539. }
  1540. ASSERT_EQ(child, waitpid(child, &status, 0));
  1541. ASSERT_EQ(1, WIFEXITED(status));
  1542. ASSERT_EQ(err ? 2 : 0, WEXITSTATUS(status))
  1543. {
  1544. TH_LOG("Unexpected return code for \"%s\": %s", path,
  1545. strerror(errno));
  1546. };
  1547. }
  1548. TEST_F_FORK(layout1, execute)
  1549. {
  1550. const struct rule rules[] = {
  1551. {
  1552. .path = dir_s1d2,
  1553. .access = LANDLOCK_ACCESS_FS_EXECUTE,
  1554. },
  1555. {},
  1556. };
  1557. const int ruleset_fd =
  1558. create_ruleset(_metadata, rules[0].access, rules);
  1559. ASSERT_LE(0, ruleset_fd);
  1560. copy_binary(_metadata, file1_s1d1);
  1561. copy_binary(_metadata, file1_s1d2);
  1562. copy_binary(_metadata, file1_s1d3);
  1563. enforce_ruleset(_metadata, ruleset_fd);
  1564. ASSERT_EQ(0, close(ruleset_fd));
  1565. ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
  1566. ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
  1567. test_execute(_metadata, EACCES, file1_s1d1);
  1568. ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
  1569. ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
  1570. test_execute(_metadata, 0, file1_s1d2);
  1571. ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
  1572. ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
  1573. test_execute(_metadata, 0, file1_s1d3);
  1574. }
  1575. TEST_F_FORK(layout1, link)
  1576. {
  1577. const struct rule layer1[] = {
  1578. {
  1579. .path = dir_s1d2,
  1580. .access = LANDLOCK_ACCESS_FS_MAKE_REG,
  1581. },
  1582. {},
  1583. };
  1584. const struct rule layer2[] = {
  1585. {
  1586. .path = dir_s1d3,
  1587. .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
  1588. },
  1589. {},
  1590. };
  1591. int ruleset_fd = create_ruleset(_metadata, layer1[0].access, layer1);
  1592. ASSERT_LE(0, ruleset_fd);
  1593. ASSERT_EQ(0, unlink(file1_s1d1));
  1594. ASSERT_EQ(0, unlink(file1_s1d2));
  1595. ASSERT_EQ(0, unlink(file1_s1d3));
  1596. enforce_ruleset(_metadata, ruleset_fd);
  1597. ASSERT_EQ(0, close(ruleset_fd));
  1598. ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
  1599. ASSERT_EQ(EACCES, errno);
  1600. /* Denies linking because of reparenting. */
  1601. ASSERT_EQ(-1, link(file1_s2d1, file1_s1d2));
  1602. ASSERT_EQ(EXDEV, errno);
  1603. ASSERT_EQ(-1, link(file2_s1d2, file1_s1d3));
  1604. ASSERT_EQ(EXDEV, errno);
  1605. ASSERT_EQ(-1, link(file2_s1d3, file1_s1d2));
  1606. ASSERT_EQ(EXDEV, errno);
  1607. ASSERT_EQ(0, link(file2_s1d2, file1_s1d2));
  1608. ASSERT_EQ(0, link(file2_s1d3, file1_s1d3));
  1609. /* Prepares for next unlinks. */
  1610. ASSERT_EQ(0, unlink(file2_s1d2));
  1611. ASSERT_EQ(0, unlink(file2_s1d3));
  1612. ruleset_fd = create_ruleset(_metadata, layer2[0].access, layer2);
  1613. ASSERT_LE(0, ruleset_fd);
  1614. enforce_ruleset(_metadata, ruleset_fd);
  1615. ASSERT_EQ(0, close(ruleset_fd));
  1616. /* Checks that linkind doesn't require the ability to delete a file. */
  1617. ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
  1618. ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
  1619. }
  1620. static int test_rename(const char *const oldpath, const char *const newpath)
  1621. {
  1622. if (rename(oldpath, newpath))
  1623. return errno;
  1624. return 0;
  1625. }
  1626. static int test_exchange(const char *const oldpath, const char *const newpath)
  1627. {
  1628. if (renameat2(AT_FDCWD, oldpath, AT_FDCWD, newpath, RENAME_EXCHANGE))
  1629. return errno;
  1630. return 0;
  1631. }
  1632. TEST_F_FORK(layout1, rename_file)
  1633. {
  1634. const struct rule rules[] = {
  1635. {
  1636. .path = dir_s1d3,
  1637. .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
  1638. },
  1639. {
  1640. .path = dir_s2d2,
  1641. .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
  1642. },
  1643. {},
  1644. };
  1645. const int ruleset_fd =
  1646. create_ruleset(_metadata, rules[0].access, rules);
  1647. ASSERT_LE(0, ruleset_fd);
  1648. ASSERT_EQ(0, unlink(file1_s1d2));
  1649. enforce_ruleset(_metadata, ruleset_fd);
  1650. ASSERT_EQ(0, close(ruleset_fd));
  1651. /*
  1652. * Tries to replace a file, from a directory that allows file removal,
  1653. * but to a different directory (which also allows file removal).
  1654. */
  1655. ASSERT_EQ(-1, rename(file1_s2d3, file1_s1d3));
  1656. ASSERT_EQ(EXDEV, errno);
  1657. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d3,
  1658. RENAME_EXCHANGE));
  1659. ASSERT_EQ(EXDEV, errno);
  1660. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, dir_s1d3,
  1661. RENAME_EXCHANGE));
  1662. ASSERT_EQ(EXDEV, errno);
  1663. /*
  1664. * Tries to replace a file, from a directory that denies file removal,
  1665. * to a different directory (which allows file removal).
  1666. */
  1667. ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
  1668. ASSERT_EQ(EACCES, errno);
  1669. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file1_s1d3,
  1670. RENAME_EXCHANGE));
  1671. ASSERT_EQ(EACCES, errno);
  1672. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s1d3,
  1673. RENAME_EXCHANGE));
  1674. ASSERT_EQ(EXDEV, errno);
  1675. /* Exchanges files and directories that partially allow removal. */
  1676. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s2d1,
  1677. RENAME_EXCHANGE));
  1678. ASSERT_EQ(EACCES, errno);
  1679. /* Checks that file1_s2d1 cannot be removed (instead of ENOTDIR). */
  1680. ASSERT_EQ(-1, rename(dir_s2d2, file1_s2d1));
  1681. ASSERT_EQ(EACCES, errno);
  1682. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, dir_s2d2,
  1683. RENAME_EXCHANGE));
  1684. ASSERT_EQ(EACCES, errno);
  1685. /* Checks that file1_s1d1 cannot be removed (instead of EISDIR). */
  1686. ASSERT_EQ(-1, rename(file1_s1d1, dir_s1d2));
  1687. ASSERT_EQ(EACCES, errno);
  1688. /* Renames files with different parents. */
  1689. ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d2));
  1690. ASSERT_EQ(EXDEV, errno);
  1691. ASSERT_EQ(0, unlink(file1_s1d3));
  1692. ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
  1693. ASSERT_EQ(EACCES, errno);
  1694. /* Exchanges and renames files with same parent. */
  1695. ASSERT_EQ(0, renameat2(AT_FDCWD, file2_s2d3, AT_FDCWD, file1_s2d3,
  1696. RENAME_EXCHANGE));
  1697. ASSERT_EQ(0, rename(file2_s2d3, file1_s2d3));
  1698. /* Exchanges files and directories with same parent, twice. */
  1699. ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
  1700. RENAME_EXCHANGE));
  1701. ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
  1702. RENAME_EXCHANGE));
  1703. }
  1704. TEST_F_FORK(layout1, rename_dir)
  1705. {
  1706. const struct rule rules[] = {
  1707. {
  1708. .path = dir_s1d2,
  1709. .access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
  1710. },
  1711. {
  1712. .path = dir_s2d1,
  1713. .access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
  1714. },
  1715. {},
  1716. };
  1717. const int ruleset_fd =
  1718. create_ruleset(_metadata, rules[0].access, rules);
  1719. ASSERT_LE(0, ruleset_fd);
  1720. /* Empties dir_s1d3 to allow renaming. */
  1721. ASSERT_EQ(0, unlink(file1_s1d3));
  1722. ASSERT_EQ(0, unlink(file2_s1d3));
  1723. enforce_ruleset(_metadata, ruleset_fd);
  1724. ASSERT_EQ(0, close(ruleset_fd));
  1725. /* Exchanges and renames directory to a different parent. */
  1726. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
  1727. RENAME_EXCHANGE));
  1728. ASSERT_EQ(EXDEV, errno);
  1729. ASSERT_EQ(-1, rename(dir_s2d3, dir_s1d3));
  1730. ASSERT_EQ(EXDEV, errno);
  1731. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
  1732. RENAME_EXCHANGE));
  1733. ASSERT_EQ(EXDEV, errno);
  1734. /*
  1735. * Exchanges directory to the same parent, which doesn't allow
  1736. * directory removal.
  1737. */
  1738. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d1, AT_FDCWD, dir_s2d1,
  1739. RENAME_EXCHANGE));
  1740. ASSERT_EQ(EACCES, errno);
  1741. /* Checks that dir_s1d2 cannot be removed (instead of ENOTDIR). */
  1742. ASSERT_EQ(-1, rename(dir_s1d2, file1_s1d1));
  1743. ASSERT_EQ(EACCES, errno);
  1744. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s1d2,
  1745. RENAME_EXCHANGE));
  1746. ASSERT_EQ(EACCES, errno);
  1747. /* Checks that dir_s1d2 cannot be removed (instead of EISDIR). */
  1748. ASSERT_EQ(-1, rename(file1_s1d1, dir_s1d2));
  1749. ASSERT_EQ(EACCES, errno);
  1750. /*
  1751. * Exchanges and renames directory to the same parent, which allows
  1752. * directory removal.
  1753. */
  1754. ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, file1_s1d2,
  1755. RENAME_EXCHANGE));
  1756. ASSERT_EQ(0, unlink(dir_s1d3));
  1757. ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
  1758. ASSERT_EQ(0, rename(file1_s1d2, dir_s1d3));
  1759. ASSERT_EQ(0, rmdir(dir_s1d3));
  1760. }
  1761. TEST_F_FORK(layout1, reparent_refer)
  1762. {
  1763. const struct rule layer1[] = {
  1764. {
  1765. .path = dir_s1d2,
  1766. .access = LANDLOCK_ACCESS_FS_REFER,
  1767. },
  1768. {
  1769. .path = dir_s2d2,
  1770. .access = LANDLOCK_ACCESS_FS_REFER,
  1771. },
  1772. {},
  1773. };
  1774. int ruleset_fd =
  1775. create_ruleset(_metadata, LANDLOCK_ACCESS_FS_REFER, layer1);
  1776. ASSERT_LE(0, ruleset_fd);
  1777. enforce_ruleset(_metadata, ruleset_fd);
  1778. ASSERT_EQ(0, close(ruleset_fd));
  1779. ASSERT_EQ(-1, rename(dir_s1d2, dir_s2d1));
  1780. ASSERT_EQ(EXDEV, errno);
  1781. ASSERT_EQ(-1, rename(dir_s1d2, dir_s2d2));
  1782. ASSERT_EQ(EXDEV, errno);
  1783. ASSERT_EQ(-1, rename(dir_s1d2, dir_s2d3));
  1784. ASSERT_EQ(EXDEV, errno);
  1785. ASSERT_EQ(-1, rename(dir_s1d3, dir_s2d1));
  1786. ASSERT_EQ(EXDEV, errno);
  1787. ASSERT_EQ(-1, rename(dir_s1d3, dir_s2d2));
  1788. ASSERT_EQ(EXDEV, errno);
  1789. /*
  1790. * Moving should only be allowed when the source and the destination
  1791. * parent directory have REFER.
  1792. */
  1793. ASSERT_EQ(-1, rename(dir_s1d3, dir_s2d3));
  1794. ASSERT_EQ(ENOTEMPTY, errno);
  1795. ASSERT_EQ(0, unlink(file1_s2d3));
  1796. ASSERT_EQ(0, unlink(file2_s2d3));
  1797. ASSERT_EQ(0, rename(dir_s1d3, dir_s2d3));
  1798. }
  1799. /* Checks renames beneath dir_s1d1. */
  1800. static void refer_denied_by_default(struct __test_metadata *const _metadata,
  1801. const struct rule layer1[],
  1802. const int layer1_err,
  1803. const struct rule layer2[])
  1804. {
  1805. int ruleset_fd;
  1806. ASSERT_EQ(0, unlink(file1_s1d2));
  1807. ruleset_fd = create_ruleset(_metadata, layer1[0].access, layer1);
  1808. ASSERT_LE(0, ruleset_fd);
  1809. enforce_ruleset(_metadata, ruleset_fd);
  1810. ASSERT_EQ(0, close(ruleset_fd));
  1811. /*
  1812. * If the first layer handles LANDLOCK_ACCESS_FS_REFER (according to
  1813. * layer1_err), then it allows some different-parent renames and links.
  1814. */
  1815. ASSERT_EQ(layer1_err, test_rename(file1_s1d1, file1_s1d2));
  1816. if (layer1_err == 0)
  1817. ASSERT_EQ(layer1_err, test_rename(file1_s1d2, file1_s1d1));
  1818. ASSERT_EQ(layer1_err, test_exchange(file2_s1d1, file2_s1d2));
  1819. ASSERT_EQ(layer1_err, test_exchange(file2_s1d2, file2_s1d1));
  1820. ruleset_fd = create_ruleset(_metadata, layer2[0].access, layer2);
  1821. ASSERT_LE(0, ruleset_fd);
  1822. enforce_ruleset(_metadata, ruleset_fd);
  1823. ASSERT_EQ(0, close(ruleset_fd));
  1824. /*
  1825. * Now, either the first or the second layer does not handle
  1826. * LANDLOCK_ACCESS_FS_REFER, which means that any different-parent
  1827. * renames and links are denied, thus making the layer handling
  1828. * LANDLOCK_ACCESS_FS_REFER null and void.
  1829. */
  1830. ASSERT_EQ(EXDEV, test_rename(file1_s1d1, file1_s1d2));
  1831. ASSERT_EQ(EXDEV, test_exchange(file2_s1d1, file2_s1d2));
  1832. ASSERT_EQ(EXDEV, test_exchange(file2_s1d2, file2_s1d1));
  1833. }
  1834. const struct rule layer_dir_s1d1_refer[] = {
  1835. {
  1836. .path = dir_s1d1,
  1837. .access = LANDLOCK_ACCESS_FS_REFER,
  1838. },
  1839. {},
  1840. };
  1841. const struct rule layer_dir_s1d1_execute[] = {
  1842. {
  1843. /* Matches a parent directory. */
  1844. .path = dir_s1d1,
  1845. .access = LANDLOCK_ACCESS_FS_EXECUTE,
  1846. },
  1847. {},
  1848. };
  1849. const struct rule layer_dir_s2d1_execute[] = {
  1850. {
  1851. /* Does not match a parent directory. */
  1852. .path = dir_s2d1,
  1853. .access = LANDLOCK_ACCESS_FS_EXECUTE,
  1854. },
  1855. {},
  1856. };
  1857. /*
  1858. * Tests precedence over renames: denied by default for different parent
  1859. * directories, *with* a rule matching a parent directory, but not directly
  1860. * denying access (with MAKE_REG nor REMOVE).
  1861. */
  1862. TEST_F_FORK(layout1, refer_denied_by_default1)
  1863. {
  1864. refer_denied_by_default(_metadata, layer_dir_s1d1_refer, 0,
  1865. layer_dir_s1d1_execute);
  1866. }
  1867. /*
  1868. * Same test but this time turning around the ABI version order: the first
  1869. * layer does not handle LANDLOCK_ACCESS_FS_REFER.
  1870. */
  1871. TEST_F_FORK(layout1, refer_denied_by_default2)
  1872. {
  1873. refer_denied_by_default(_metadata, layer_dir_s1d1_execute, EXDEV,
  1874. layer_dir_s1d1_refer);
  1875. }
  1876. /*
  1877. * Tests precedence over renames: denied by default for different parent
  1878. * directories, *without* a rule matching a parent directory, but not directly
  1879. * denying access (with MAKE_REG nor REMOVE).
  1880. */
  1881. TEST_F_FORK(layout1, refer_denied_by_default3)
  1882. {
  1883. refer_denied_by_default(_metadata, layer_dir_s1d1_refer, 0,
  1884. layer_dir_s2d1_execute);
  1885. }
  1886. /*
  1887. * Same test but this time turning around the ABI version order: the first
  1888. * layer does not handle LANDLOCK_ACCESS_FS_REFER.
  1889. */
  1890. TEST_F_FORK(layout1, refer_denied_by_default4)
  1891. {
  1892. refer_denied_by_default(_metadata, layer_dir_s2d1_execute, EXDEV,
  1893. layer_dir_s1d1_refer);
  1894. }
  1895. TEST_F_FORK(layout1, reparent_link)
  1896. {
  1897. const struct rule layer1[] = {
  1898. {
  1899. .path = dir_s1d2,
  1900. .access = LANDLOCK_ACCESS_FS_MAKE_REG,
  1901. },
  1902. {
  1903. .path = dir_s1d3,
  1904. .access = LANDLOCK_ACCESS_FS_REFER,
  1905. },
  1906. {
  1907. .path = dir_s2d2,
  1908. .access = LANDLOCK_ACCESS_FS_REFER,
  1909. },
  1910. {
  1911. .path = dir_s2d3,
  1912. .access = LANDLOCK_ACCESS_FS_MAKE_REG,
  1913. },
  1914. {},
  1915. };
  1916. const int ruleset_fd = create_ruleset(
  1917. _metadata,
  1918. LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER, layer1);
  1919. ASSERT_LE(0, ruleset_fd);
  1920. enforce_ruleset(_metadata, ruleset_fd);
  1921. ASSERT_EQ(0, close(ruleset_fd));
  1922. ASSERT_EQ(0, unlink(file1_s1d1));
  1923. ASSERT_EQ(0, unlink(file1_s1d2));
  1924. ASSERT_EQ(0, unlink(file1_s1d3));
  1925. /* Denies linking because of missing MAKE_REG. */
  1926. ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
  1927. ASSERT_EQ(EACCES, errno);
  1928. /* Denies linking because of missing source and destination REFER. */
  1929. ASSERT_EQ(-1, link(file1_s2d1, file1_s1d2));
  1930. ASSERT_EQ(EXDEV, errno);
  1931. /* Denies linking because of missing source REFER. */
  1932. ASSERT_EQ(-1, link(file1_s2d1, file1_s1d3));
  1933. ASSERT_EQ(EXDEV, errno);
  1934. /* Denies linking because of missing MAKE_REG. */
  1935. ASSERT_EQ(-1, link(file1_s2d2, file1_s1d1));
  1936. ASSERT_EQ(EACCES, errno);
  1937. /* Denies linking because of missing destination REFER. */
  1938. ASSERT_EQ(-1, link(file1_s2d2, file1_s1d2));
  1939. ASSERT_EQ(EXDEV, errno);
  1940. /* Allows linking because of REFER and MAKE_REG. */
  1941. ASSERT_EQ(0, link(file1_s2d2, file1_s1d3));
  1942. ASSERT_EQ(0, unlink(file1_s2d2));
  1943. /* Reverse linking denied because of missing MAKE_REG. */
  1944. ASSERT_EQ(-1, link(file1_s1d3, file1_s2d2));
  1945. ASSERT_EQ(EACCES, errno);
  1946. ASSERT_EQ(0, unlink(file1_s2d3));
  1947. /* Checks reverse linking. */
  1948. ASSERT_EQ(0, link(file1_s1d3, file1_s2d3));
  1949. ASSERT_EQ(0, unlink(file1_s1d3));
  1950. /*
  1951. * This is OK for a file link, but it should not be allowed for a
  1952. * directory rename (because of the superset of access rights.
  1953. */
  1954. ASSERT_EQ(0, link(file1_s2d3, file1_s1d3));
  1955. ASSERT_EQ(0, unlink(file1_s1d3));
  1956. ASSERT_EQ(-1, link(file2_s1d2, file1_s1d3));
  1957. ASSERT_EQ(EXDEV, errno);
  1958. ASSERT_EQ(-1, link(file2_s1d3, file1_s1d2));
  1959. ASSERT_EQ(EXDEV, errno);
  1960. ASSERT_EQ(0, link(file2_s1d2, file1_s1d2));
  1961. ASSERT_EQ(0, link(file2_s1d3, file1_s1d3));
  1962. }
  1963. TEST_F_FORK(layout1, reparent_rename)
  1964. {
  1965. /* Same rules as for reparent_link. */
  1966. const struct rule layer1[] = {
  1967. {
  1968. .path = dir_s1d2,
  1969. .access = LANDLOCK_ACCESS_FS_MAKE_REG,
  1970. },
  1971. {
  1972. .path = dir_s1d3,
  1973. .access = LANDLOCK_ACCESS_FS_REFER,
  1974. },
  1975. {
  1976. .path = dir_s2d2,
  1977. .access = LANDLOCK_ACCESS_FS_REFER,
  1978. },
  1979. {
  1980. .path = dir_s2d3,
  1981. .access = LANDLOCK_ACCESS_FS_MAKE_REG,
  1982. },
  1983. {},
  1984. };
  1985. const int ruleset_fd = create_ruleset(
  1986. _metadata,
  1987. LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER, layer1);
  1988. ASSERT_LE(0, ruleset_fd);
  1989. enforce_ruleset(_metadata, ruleset_fd);
  1990. ASSERT_EQ(0, close(ruleset_fd));
  1991. ASSERT_EQ(0, unlink(file1_s1d2));
  1992. ASSERT_EQ(0, unlink(file1_s1d3));
  1993. /* Denies renaming because of missing MAKE_REG. */
  1994. ASSERT_EQ(-1, renameat2(AT_FDCWD, file2_s1d1, AT_FDCWD, file1_s1d1,
  1995. RENAME_EXCHANGE));
  1996. ASSERT_EQ(EACCES, errno);
  1997. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, file2_s1d1,
  1998. RENAME_EXCHANGE));
  1999. ASSERT_EQ(EACCES, errno);
  2000. ASSERT_EQ(0, unlink(file1_s1d1));
  2001. ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
  2002. ASSERT_EQ(EACCES, errno);
  2003. /* Even denies same file exchange. */
  2004. ASSERT_EQ(-1, renameat2(AT_FDCWD, file2_s1d1, AT_FDCWD, file2_s1d1,
  2005. RENAME_EXCHANGE));
  2006. ASSERT_EQ(EACCES, errno);
  2007. /* Denies renaming because of missing source and destination REFER. */
  2008. ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d2));
  2009. ASSERT_EQ(EXDEV, errno);
  2010. /*
  2011. * Denies renaming because of missing MAKE_REG, source and destination
  2012. * REFER.
  2013. */
  2014. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file2_s1d1,
  2015. RENAME_EXCHANGE));
  2016. ASSERT_EQ(EACCES, errno);
  2017. ASSERT_EQ(-1, renameat2(AT_FDCWD, file2_s1d1, AT_FDCWD, file1_s2d1,
  2018. RENAME_EXCHANGE));
  2019. ASSERT_EQ(EACCES, errno);
  2020. /* Denies renaming because of missing source REFER. */
  2021. ASSERT_EQ(-1, rename(file1_s2d1, file1_s1d3));
  2022. ASSERT_EQ(EXDEV, errno);
  2023. /* Denies renaming because of missing MAKE_REG. */
  2024. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, file2_s1d3,
  2025. RENAME_EXCHANGE));
  2026. ASSERT_EQ(EACCES, errno);
  2027. /* Denies renaming because of missing MAKE_REG. */
  2028. ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d1));
  2029. ASSERT_EQ(EACCES, errno);
  2030. /* Denies renaming because of missing destination REFER*/
  2031. ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d2));
  2032. ASSERT_EQ(EXDEV, errno);
  2033. /* Denies exchange because of one missing MAKE_REG. */
  2034. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, file2_s1d3,
  2035. RENAME_EXCHANGE));
  2036. ASSERT_EQ(EACCES, errno);
  2037. /* Allows renaming because of REFER and MAKE_REG. */
  2038. ASSERT_EQ(0, rename(file1_s2d2, file1_s1d3));
  2039. /* Reverse renaming denied because of missing MAKE_REG. */
  2040. ASSERT_EQ(-1, rename(file1_s1d3, file1_s2d2));
  2041. ASSERT_EQ(EACCES, errno);
  2042. ASSERT_EQ(0, unlink(file1_s2d3));
  2043. ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
  2044. /* Tests reverse renaming. */
  2045. ASSERT_EQ(0, rename(file1_s2d3, file1_s1d3));
  2046. ASSERT_EQ(0, renameat2(AT_FDCWD, file2_s2d3, AT_FDCWD, file1_s1d3,
  2047. RENAME_EXCHANGE));
  2048. ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
  2049. /*
  2050. * This is OK for a file rename, but it should not be allowed for a
  2051. * directory rename (because of the superset of access rights).
  2052. */
  2053. ASSERT_EQ(0, rename(file1_s2d3, file1_s1d3));
  2054. ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
  2055. /*
  2056. * Tests superset restrictions applied to directories. Not only the
  2057. * dir_s2d3's parent (dir_s2d2) should be taken into account but also
  2058. * access rights tied to dir_s2d3. dir_s2d2 is missing one access right
  2059. * compared to dir_s1d3/file1_s1d3 (MAKE_REG) but it is provided
  2060. * directly by the moved dir_s2d3.
  2061. */
  2062. ASSERT_EQ(0, rename(dir_s2d3, file1_s1d3));
  2063. ASSERT_EQ(0, rename(file1_s1d3, dir_s2d3));
  2064. /*
  2065. * The first rename is allowed but not the exchange because dir_s1d3's
  2066. * parent (dir_s1d2) doesn't have REFER.
  2067. */
  2068. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, dir_s1d3,
  2069. RENAME_EXCHANGE));
  2070. ASSERT_EQ(EXDEV, errno);
  2071. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, file1_s2d3,
  2072. RENAME_EXCHANGE));
  2073. ASSERT_EQ(EXDEV, errno);
  2074. ASSERT_EQ(-1, rename(file1_s2d3, dir_s1d3));
  2075. ASSERT_EQ(EXDEV, errno);
  2076. ASSERT_EQ(-1, rename(file2_s1d2, file1_s1d3));
  2077. ASSERT_EQ(EXDEV, errno);
  2078. ASSERT_EQ(-1, rename(file2_s1d3, file1_s1d2));
  2079. ASSERT_EQ(EXDEV, errno);
  2080. /* Renaming in the same directory is always allowed. */
  2081. ASSERT_EQ(0, rename(file2_s1d2, file1_s1d2));
  2082. ASSERT_EQ(0, rename(file2_s1d3, file1_s1d3));
  2083. ASSERT_EQ(0, unlink(file1_s1d2));
  2084. /* Denies because of missing source MAKE_REG and destination REFER. */
  2085. ASSERT_EQ(-1, rename(dir_s2d3, file1_s1d2));
  2086. ASSERT_EQ(EXDEV, errno);
  2087. ASSERT_EQ(0, unlink(file1_s1d3));
  2088. /* Denies because of missing source MAKE_REG and REFER. */
  2089. ASSERT_EQ(-1, rename(dir_s2d2, file1_s1d3));
  2090. ASSERT_EQ(EXDEV, errno);
  2091. }
  2092. static void
  2093. reparent_exdev_layers_enforce1(struct __test_metadata *const _metadata)
  2094. {
  2095. const struct rule layer1[] = {
  2096. {
  2097. .path = dir_s1d2,
  2098. .access = LANDLOCK_ACCESS_FS_REFER,
  2099. },
  2100. {
  2101. /* Interesting for the layer2 tests. */
  2102. .path = dir_s1d3,
  2103. .access = LANDLOCK_ACCESS_FS_MAKE_REG,
  2104. },
  2105. {
  2106. .path = dir_s2d2,
  2107. .access = LANDLOCK_ACCESS_FS_REFER,
  2108. },
  2109. {
  2110. .path = dir_s2d3,
  2111. .access = LANDLOCK_ACCESS_FS_MAKE_REG,
  2112. },
  2113. {},
  2114. };
  2115. const int ruleset_fd = create_ruleset(
  2116. _metadata,
  2117. LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_REFER, layer1);
  2118. ASSERT_LE(0, ruleset_fd);
  2119. enforce_ruleset(_metadata, ruleset_fd);
  2120. ASSERT_EQ(0, close(ruleset_fd));
  2121. }
  2122. static void
  2123. reparent_exdev_layers_enforce2(struct __test_metadata *const _metadata)
  2124. {
  2125. const struct rule layer2[] = {
  2126. {
  2127. .path = dir_s2d3,
  2128. .access = LANDLOCK_ACCESS_FS_MAKE_DIR,
  2129. },
  2130. {},
  2131. };
  2132. /*
  2133. * Same checks as before but with a second layer and a new MAKE_DIR
  2134. * rule (and no explicit handling of REFER).
  2135. */
  2136. const int ruleset_fd =
  2137. create_ruleset(_metadata, LANDLOCK_ACCESS_FS_MAKE_DIR, layer2);
  2138. ASSERT_LE(0, ruleset_fd);
  2139. enforce_ruleset(_metadata, ruleset_fd);
  2140. ASSERT_EQ(0, close(ruleset_fd));
  2141. }
  2142. TEST_F_FORK(layout1, reparent_exdev_layers_rename1)
  2143. {
  2144. ASSERT_EQ(0, unlink(file1_s2d2));
  2145. ASSERT_EQ(0, unlink(file1_s2d3));
  2146. reparent_exdev_layers_enforce1(_metadata);
  2147. /*
  2148. * Moving the dir_s1d3 directory below dir_s2d2 is allowed by Landlock
  2149. * because it doesn't inherit new access rights.
  2150. */
  2151. ASSERT_EQ(0, rename(dir_s1d3, file1_s2d2));
  2152. ASSERT_EQ(0, rename(file1_s2d2, dir_s1d3));
  2153. /*
  2154. * Moving the dir_s1d3 directory below dir_s2d3 is allowed, even if it
  2155. * gets a new inherited access rights (MAKE_REG), because MAKE_REG is
  2156. * already allowed for dir_s1d3.
  2157. */
  2158. ASSERT_EQ(0, rename(dir_s1d3, file1_s2d3));
  2159. ASSERT_EQ(0, rename(file1_s2d3, dir_s1d3));
  2160. /*
  2161. * However, moving the file1_s1d3 file below dir_s2d3 is allowed
  2162. * because it cannot inherit MAKE_REG right (which is dedicated to
  2163. * directories).
  2164. */
  2165. ASSERT_EQ(0, rename(file1_s1d3, file1_s2d3));
  2166. reparent_exdev_layers_enforce2(_metadata);
  2167. /*
  2168. * Moving the dir_s1d3 directory below dir_s2d2 is now denied because
  2169. * MAKE_DIR is not tied to dir_s2d2.
  2170. */
  2171. ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d2));
  2172. ASSERT_EQ(EACCES, errno);
  2173. /*
  2174. * Moving the dir_s1d3 directory below dir_s2d3 is forbidden because it
  2175. * would grants MAKE_REG and MAKE_DIR rights to it.
  2176. */
  2177. ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d3));
  2178. ASSERT_EQ(EXDEV, errno);
  2179. /*
  2180. * Moving the file2_s1d3 file below dir_s2d3 is denied because the
  2181. * second layer does not handle REFER, which is always denied by
  2182. * default.
  2183. */
  2184. ASSERT_EQ(-1, rename(file2_s1d3, file1_s2d3));
  2185. ASSERT_EQ(EXDEV, errno);
  2186. }
  2187. TEST_F_FORK(layout1, reparent_exdev_layers_rename2)
  2188. {
  2189. reparent_exdev_layers_enforce1(_metadata);
  2190. /* Checks EACCES predominance over EXDEV. */
  2191. ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d2));
  2192. ASSERT_EQ(EACCES, errno);
  2193. ASSERT_EQ(-1, rename(file1_s1d2, file1_s2d2));
  2194. ASSERT_EQ(EACCES, errno);
  2195. ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d3));
  2196. ASSERT_EQ(EXDEV, errno);
  2197. /* Modify layout! */
  2198. ASSERT_EQ(0, rename(file1_s1d2, file1_s2d3));
  2199. /* Without REFER source. */
  2200. ASSERT_EQ(-1, rename(dir_s1d1, file1_s2d2));
  2201. ASSERT_EQ(EXDEV, errno);
  2202. ASSERT_EQ(-1, rename(dir_s1d2, file1_s2d2));
  2203. ASSERT_EQ(EXDEV, errno);
  2204. reparent_exdev_layers_enforce2(_metadata);
  2205. /* Checks EACCES predominance over EXDEV. */
  2206. ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d2));
  2207. ASSERT_EQ(EACCES, errno);
  2208. /* Checks with actual file2_s1d2. */
  2209. ASSERT_EQ(-1, rename(file2_s1d2, file1_s2d2));
  2210. ASSERT_EQ(EACCES, errno);
  2211. ASSERT_EQ(-1, rename(file1_s1d1, file1_s2d3));
  2212. ASSERT_EQ(EXDEV, errno);
  2213. /*
  2214. * Modifying the layout is now denied because the second layer does not
  2215. * handle REFER, which is always denied by default.
  2216. */
  2217. ASSERT_EQ(-1, rename(file2_s1d2, file1_s2d3));
  2218. ASSERT_EQ(EXDEV, errno);
  2219. /* Without REFER source, EACCES wins over EXDEV. */
  2220. ASSERT_EQ(-1, rename(dir_s1d1, file1_s2d2));
  2221. ASSERT_EQ(EACCES, errno);
  2222. ASSERT_EQ(-1, rename(dir_s1d2, file1_s2d2));
  2223. ASSERT_EQ(EACCES, errno);
  2224. }
  2225. TEST_F_FORK(layout1, reparent_exdev_layers_exchange1)
  2226. {
  2227. const char *const dir_file1_s1d2 = file1_s1d2, *const dir_file2_s2d3 =
  2228. file2_s2d3;
  2229. ASSERT_EQ(0, unlink(file1_s1d2));
  2230. ASSERT_EQ(0, mkdir(file1_s1d2, 0700));
  2231. ASSERT_EQ(0, unlink(file2_s2d3));
  2232. ASSERT_EQ(0, mkdir(file2_s2d3, 0700));
  2233. reparent_exdev_layers_enforce1(_metadata);
  2234. /* Error predominance with file exchange: returns EXDEV and EACCES. */
  2235. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, file1_s2d3,
  2236. RENAME_EXCHANGE));
  2237. ASSERT_EQ(EACCES, errno);
  2238. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d1,
  2239. RENAME_EXCHANGE));
  2240. ASSERT_EQ(EACCES, errno);
  2241. /*
  2242. * Checks with directories which creation could be allowed, but denied
  2243. * because of access rights that would be inherited.
  2244. */
  2245. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD,
  2246. dir_file2_s2d3, RENAME_EXCHANGE));
  2247. ASSERT_EQ(EXDEV, errno);
  2248. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD,
  2249. dir_file1_s1d2, RENAME_EXCHANGE));
  2250. ASSERT_EQ(EXDEV, errno);
  2251. /* Checks with same access rights. */
  2252. ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, dir_s2d3,
  2253. RENAME_EXCHANGE));
  2254. ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
  2255. RENAME_EXCHANGE));
  2256. /* Checks with different (child-only) access rights. */
  2257. ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_file1_s1d2,
  2258. RENAME_EXCHANGE));
  2259. ASSERT_EQ(0, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD, dir_s2d3,
  2260. RENAME_EXCHANGE));
  2261. /*
  2262. * Checks that exchange between file and directory are consistent.
  2263. *
  2264. * Moving a file (file1_s2d2) to a directory which only grants more
  2265. * directory-related access rights is allowed, and at the same time
  2266. * moving a directory (dir_file2_s2d3) to another directory which
  2267. * grants less access rights is allowed too.
  2268. *
  2269. * See layout1.reparent_exdev_layers_exchange3 for inverted arguments.
  2270. */
  2271. ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
  2272. RENAME_EXCHANGE));
  2273. /*
  2274. * However, moving back the directory is denied because it would get
  2275. * more access rights than the current state and because file creation
  2276. * is forbidden (in dir_s2d2).
  2277. */
  2278. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
  2279. RENAME_EXCHANGE));
  2280. ASSERT_EQ(EACCES, errno);
  2281. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
  2282. RENAME_EXCHANGE));
  2283. ASSERT_EQ(EACCES, errno);
  2284. reparent_exdev_layers_enforce2(_metadata);
  2285. /* Error predominance with file exchange: returns EXDEV and EACCES. */
  2286. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, file1_s2d3,
  2287. RENAME_EXCHANGE));
  2288. ASSERT_EQ(EACCES, errno);
  2289. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d3, AT_FDCWD, file1_s1d1,
  2290. RENAME_EXCHANGE));
  2291. ASSERT_EQ(EACCES, errno);
  2292. /* Checks with directories which creation is now denied. */
  2293. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD,
  2294. dir_file2_s2d3, RENAME_EXCHANGE));
  2295. ASSERT_EQ(EACCES, errno);
  2296. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD,
  2297. dir_file1_s1d2, RENAME_EXCHANGE));
  2298. ASSERT_EQ(EACCES, errno);
  2299. /* Checks with different (child-only) access rights. */
  2300. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, dir_s2d3,
  2301. RENAME_EXCHANGE));
  2302. /* Denied because of MAKE_DIR. */
  2303. ASSERT_EQ(EACCES, errno);
  2304. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_s1d3,
  2305. RENAME_EXCHANGE));
  2306. ASSERT_EQ(EACCES, errno);
  2307. /* Checks with different (child-only) access rights. */
  2308. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d3, AT_FDCWD, dir_file1_s1d2,
  2309. RENAME_EXCHANGE));
  2310. /* Denied because of MAKE_DIR. */
  2311. ASSERT_EQ(EACCES, errno);
  2312. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file1_s1d2, AT_FDCWD, dir_s2d3,
  2313. RENAME_EXCHANGE));
  2314. ASSERT_EQ(EACCES, errno);
  2315. /* See layout1.reparent_exdev_layers_exchange2 for complement. */
  2316. }
  2317. TEST_F_FORK(layout1, reparent_exdev_layers_exchange2)
  2318. {
  2319. const char *const dir_file2_s2d3 = file2_s2d3;
  2320. ASSERT_EQ(0, unlink(file2_s2d3));
  2321. ASSERT_EQ(0, mkdir(file2_s2d3, 0700));
  2322. reparent_exdev_layers_enforce1(_metadata);
  2323. reparent_exdev_layers_enforce2(_metadata);
  2324. /* Checks that exchange between file and directory are consistent. */
  2325. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
  2326. RENAME_EXCHANGE));
  2327. ASSERT_EQ(EACCES, errno);
  2328. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
  2329. RENAME_EXCHANGE));
  2330. ASSERT_EQ(EACCES, errno);
  2331. }
  2332. TEST_F_FORK(layout1, reparent_exdev_layers_exchange3)
  2333. {
  2334. const char *const dir_file2_s2d3 = file2_s2d3;
  2335. ASSERT_EQ(0, unlink(file2_s2d3));
  2336. ASSERT_EQ(0, mkdir(file2_s2d3, 0700));
  2337. reparent_exdev_layers_enforce1(_metadata);
  2338. /*
  2339. * Checks that exchange between file and directory are consistent,
  2340. * including with inverted arguments (see
  2341. * layout1.reparent_exdev_layers_exchange1).
  2342. */
  2343. ASSERT_EQ(0, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
  2344. RENAME_EXCHANGE));
  2345. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_file2_s2d3,
  2346. RENAME_EXCHANGE));
  2347. ASSERT_EQ(EACCES, errno);
  2348. ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_file2_s2d3, AT_FDCWD, file1_s2d2,
  2349. RENAME_EXCHANGE));
  2350. ASSERT_EQ(EACCES, errno);
  2351. }
  2352. TEST_F_FORK(layout1, reparent_remove)
  2353. {
  2354. const struct rule layer1[] = {
  2355. {
  2356. .path = dir_s1d1,
  2357. .access = LANDLOCK_ACCESS_FS_REFER |
  2358. LANDLOCK_ACCESS_FS_REMOVE_DIR,
  2359. },
  2360. {
  2361. .path = dir_s1d2,
  2362. .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
  2363. },
  2364. {
  2365. .path = dir_s2d1,
  2366. .access = LANDLOCK_ACCESS_FS_REFER |
  2367. LANDLOCK_ACCESS_FS_REMOVE_FILE,
  2368. },
  2369. {},
  2370. };
  2371. const int ruleset_fd = create_ruleset(
  2372. _metadata,
  2373. LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_REMOVE_DIR |
  2374. LANDLOCK_ACCESS_FS_REMOVE_FILE,
  2375. layer1);
  2376. ASSERT_LE(0, ruleset_fd);
  2377. enforce_ruleset(_metadata, ruleset_fd);
  2378. ASSERT_EQ(0, close(ruleset_fd));
  2379. /* Access denied because of wrong/swapped remove file/dir. */
  2380. ASSERT_EQ(-1, rename(file1_s1d1, dir_s2d2));
  2381. ASSERT_EQ(EACCES, errno);
  2382. ASSERT_EQ(-1, rename(dir_s2d2, file1_s1d1));
  2383. ASSERT_EQ(EACCES, errno);
  2384. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s2d2,
  2385. RENAME_EXCHANGE));
  2386. ASSERT_EQ(EACCES, errno);
  2387. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s2d3,
  2388. RENAME_EXCHANGE));
  2389. ASSERT_EQ(EACCES, errno);
  2390. /* Access allowed thanks to the matching rights. */
  2391. ASSERT_EQ(-1, rename(file1_s2d1, dir_s1d2));
  2392. ASSERT_EQ(EISDIR, errno);
  2393. ASSERT_EQ(-1, rename(dir_s1d2, file1_s2d1));
  2394. ASSERT_EQ(ENOTDIR, errno);
  2395. ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d1));
  2396. ASSERT_EQ(ENOTDIR, errno);
  2397. ASSERT_EQ(0, unlink(file1_s2d1));
  2398. ASSERT_EQ(0, unlink(file1_s1d3));
  2399. ASSERT_EQ(0, unlink(file2_s1d3));
  2400. ASSERT_EQ(0, rename(dir_s1d3, file1_s2d1));
  2401. /* Effectively removes a file and a directory by exchanging them. */
  2402. ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
  2403. ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
  2404. RENAME_EXCHANGE));
  2405. ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s1d3,
  2406. RENAME_EXCHANGE));
  2407. ASSERT_EQ(EACCES, errno);
  2408. }
  2409. TEST_F_FORK(layout1, reparent_dom_superset)
  2410. {
  2411. const struct rule layer1[] = {
  2412. {
  2413. .path = dir_s1d2,
  2414. .access = LANDLOCK_ACCESS_FS_REFER,
  2415. },
  2416. {
  2417. .path = file1_s1d2,
  2418. .access = LANDLOCK_ACCESS_FS_EXECUTE,
  2419. },
  2420. {
  2421. .path = dir_s1d3,
  2422. .access = LANDLOCK_ACCESS_FS_MAKE_SOCK |
  2423. LANDLOCK_ACCESS_FS_EXECUTE,
  2424. },
  2425. {
  2426. .path = dir_s2d2,
  2427. .access = LANDLOCK_ACCESS_FS_REFER |
  2428. LANDLOCK_ACCESS_FS_EXECUTE |
  2429. LANDLOCK_ACCESS_FS_MAKE_SOCK,
  2430. },
  2431. {
  2432. .path = dir_s2d3,
  2433. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  2434. LANDLOCK_ACCESS_FS_MAKE_FIFO,
  2435. },
  2436. {},
  2437. };
  2438. int ruleset_fd = create_ruleset(_metadata,
  2439. LANDLOCK_ACCESS_FS_REFER |
  2440. LANDLOCK_ACCESS_FS_EXECUTE |
  2441. LANDLOCK_ACCESS_FS_MAKE_SOCK |
  2442. LANDLOCK_ACCESS_FS_READ_FILE |
  2443. LANDLOCK_ACCESS_FS_MAKE_FIFO,
  2444. layer1);
  2445. ASSERT_LE(0, ruleset_fd);
  2446. enforce_ruleset(_metadata, ruleset_fd);
  2447. ASSERT_EQ(0, close(ruleset_fd));
  2448. ASSERT_EQ(-1, rename(file1_s1d2, file1_s2d1));
  2449. ASSERT_EQ(EXDEV, errno);
  2450. /*
  2451. * Moving file1_s1d2 beneath dir_s2d3 would grant it the READ_FILE
  2452. * access right.
  2453. */
  2454. ASSERT_EQ(-1, rename(file1_s1d2, file1_s2d3));
  2455. ASSERT_EQ(EXDEV, errno);
  2456. /*
  2457. * Moving file1_s1d2 should be allowed even if dir_s2d2 grants a
  2458. * superset of access rights compared to dir_s1d2, because file1_s1d2
  2459. * already has these access rights anyway.
  2460. */
  2461. ASSERT_EQ(0, rename(file1_s1d2, file1_s2d2));
  2462. ASSERT_EQ(0, rename(file1_s2d2, file1_s1d2));
  2463. ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d1));
  2464. ASSERT_EQ(EXDEV, errno);
  2465. /*
  2466. * Moving dir_s1d3 beneath dir_s2d3 would grant it the MAKE_FIFO access
  2467. * right.
  2468. */
  2469. ASSERT_EQ(-1, rename(dir_s1d3, file1_s2d3));
  2470. ASSERT_EQ(EXDEV, errno);
  2471. /*
  2472. * Moving dir_s1d3 should be allowed even if dir_s2d2 grants a superset
  2473. * of access rights compared to dir_s1d2, because dir_s1d3 already has
  2474. * these access rights anyway.
  2475. */
  2476. ASSERT_EQ(0, rename(dir_s1d3, file1_s2d2));
  2477. ASSERT_EQ(0, rename(file1_s2d2, dir_s1d3));
  2478. /*
  2479. * Moving file1_s2d3 beneath dir_s1d2 is allowed, but moving it back
  2480. * will be denied because the new inherited access rights from dir_s1d2
  2481. * will be less than the destination (original) dir_s2d3. This is a
  2482. * sinkhole scenario where we cannot move back files or directories.
  2483. */
  2484. ASSERT_EQ(0, rename(file1_s2d3, file2_s1d2));
  2485. ASSERT_EQ(-1, rename(file2_s1d2, file1_s2d3));
  2486. ASSERT_EQ(EXDEV, errno);
  2487. ASSERT_EQ(0, unlink(file2_s1d2));
  2488. ASSERT_EQ(0, unlink(file2_s2d3));
  2489. /*
  2490. * Checks similar directory one-way move: dir_s2d3 loses EXECUTE and
  2491. * MAKE_SOCK which were inherited from dir_s1d3.
  2492. */
  2493. ASSERT_EQ(0, rename(dir_s2d3, file2_s1d2));
  2494. ASSERT_EQ(-1, rename(file2_s1d2, dir_s2d3));
  2495. ASSERT_EQ(EXDEV, errno);
  2496. }
  2497. TEST_F_FORK(layout1, remove_dir)
  2498. {
  2499. const struct rule rules[] = {
  2500. {
  2501. .path = dir_s1d2,
  2502. .access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
  2503. },
  2504. {},
  2505. };
  2506. const int ruleset_fd =
  2507. create_ruleset(_metadata, rules[0].access, rules);
  2508. ASSERT_LE(0, ruleset_fd);
  2509. ASSERT_EQ(0, unlink(file1_s1d1));
  2510. ASSERT_EQ(0, unlink(file1_s1d2));
  2511. ASSERT_EQ(0, unlink(file1_s1d3));
  2512. ASSERT_EQ(0, unlink(file2_s1d3));
  2513. enforce_ruleset(_metadata, ruleset_fd);
  2514. ASSERT_EQ(0, close(ruleset_fd));
  2515. ASSERT_EQ(0, rmdir(dir_s1d3));
  2516. ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
  2517. ASSERT_EQ(0, unlinkat(AT_FDCWD, dir_s1d3, AT_REMOVEDIR));
  2518. /* dir_s1d2 itself cannot be removed. */
  2519. ASSERT_EQ(-1, rmdir(dir_s1d2));
  2520. ASSERT_EQ(EACCES, errno);
  2521. ASSERT_EQ(-1, unlinkat(AT_FDCWD, dir_s1d2, AT_REMOVEDIR));
  2522. ASSERT_EQ(EACCES, errno);
  2523. ASSERT_EQ(-1, rmdir(dir_s1d1));
  2524. ASSERT_EQ(EACCES, errno);
  2525. ASSERT_EQ(-1, unlinkat(AT_FDCWD, dir_s1d1, AT_REMOVEDIR));
  2526. ASSERT_EQ(EACCES, errno);
  2527. }
  2528. TEST_F_FORK(layout1, remove_file)
  2529. {
  2530. const struct rule rules[] = {
  2531. {
  2532. .path = dir_s1d2,
  2533. .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
  2534. },
  2535. {},
  2536. };
  2537. const int ruleset_fd =
  2538. create_ruleset(_metadata, rules[0].access, rules);
  2539. ASSERT_LE(0, ruleset_fd);
  2540. enforce_ruleset(_metadata, ruleset_fd);
  2541. ASSERT_EQ(0, close(ruleset_fd));
  2542. ASSERT_EQ(-1, unlink(file1_s1d1));
  2543. ASSERT_EQ(EACCES, errno);
  2544. ASSERT_EQ(-1, unlinkat(AT_FDCWD, file1_s1d1, 0));
  2545. ASSERT_EQ(EACCES, errno);
  2546. ASSERT_EQ(0, unlink(file1_s1d2));
  2547. ASSERT_EQ(0, unlinkat(AT_FDCWD, file1_s1d3, 0));
  2548. }
  2549. static void test_make_file(struct __test_metadata *const _metadata,
  2550. const __u64 access, const mode_t mode,
  2551. const dev_t dev)
  2552. {
  2553. const struct rule rules[] = {
  2554. {
  2555. .path = dir_s1d2,
  2556. .access = access,
  2557. },
  2558. {},
  2559. };
  2560. const int ruleset_fd = create_ruleset(_metadata, access, rules);
  2561. ASSERT_LE(0, ruleset_fd);
  2562. ASSERT_EQ(0, unlink(file1_s1d1));
  2563. ASSERT_EQ(0, unlink(file2_s1d1));
  2564. ASSERT_EQ(0, mknod(file2_s1d1, mode | 0400, dev))
  2565. {
  2566. TH_LOG("Failed to make file \"%s\": %s", file2_s1d1,
  2567. strerror(errno));
  2568. };
  2569. ASSERT_EQ(0, unlink(file1_s1d2));
  2570. ASSERT_EQ(0, unlink(file2_s1d2));
  2571. ASSERT_EQ(0, unlink(file1_s1d3));
  2572. ASSERT_EQ(0, unlink(file2_s1d3));
  2573. enforce_ruleset(_metadata, ruleset_fd);
  2574. ASSERT_EQ(0, close(ruleset_fd));
  2575. ASSERT_EQ(-1, mknod(file1_s1d1, mode | 0400, dev));
  2576. ASSERT_EQ(EACCES, errno);
  2577. ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
  2578. ASSERT_EQ(EACCES, errno);
  2579. ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
  2580. ASSERT_EQ(EACCES, errno);
  2581. ASSERT_EQ(0, mknod(file1_s1d2, mode | 0400, dev))
  2582. {
  2583. TH_LOG("Failed to make file \"%s\": %s", file1_s1d2,
  2584. strerror(errno));
  2585. };
  2586. ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
  2587. ASSERT_EQ(0, unlink(file2_s1d2));
  2588. ASSERT_EQ(0, rename(file1_s1d2, file2_s1d2));
  2589. ASSERT_EQ(0, mknod(file1_s1d3, mode | 0400, dev));
  2590. ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
  2591. ASSERT_EQ(0, unlink(file2_s1d3));
  2592. ASSERT_EQ(0, rename(file1_s1d3, file2_s1d3));
  2593. }
  2594. TEST_F_FORK(layout1, make_char)
  2595. {
  2596. /* Creates a /dev/null device. */
  2597. set_cap(_metadata, CAP_MKNOD);
  2598. test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_CHAR, S_IFCHR,
  2599. makedev(1, 3));
  2600. }
  2601. TEST_F_FORK(layout1, make_block)
  2602. {
  2603. /* Creates a /dev/loop0 device. */
  2604. set_cap(_metadata, CAP_MKNOD);
  2605. test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_BLOCK, S_IFBLK,
  2606. makedev(7, 0));
  2607. }
  2608. TEST_F_FORK(layout1, make_reg_1)
  2609. {
  2610. test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, S_IFREG, 0);
  2611. }
  2612. TEST_F_FORK(layout1, make_reg_2)
  2613. {
  2614. test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, 0, 0);
  2615. }
  2616. TEST_F_FORK(layout1, make_sock)
  2617. {
  2618. test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_SOCK, S_IFSOCK, 0);
  2619. }
  2620. TEST_F_FORK(layout1, make_fifo)
  2621. {
  2622. test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_FIFO, S_IFIFO, 0);
  2623. }
  2624. TEST_F_FORK(layout1, make_sym)
  2625. {
  2626. const struct rule rules[] = {
  2627. {
  2628. .path = dir_s1d2,
  2629. .access = LANDLOCK_ACCESS_FS_MAKE_SYM,
  2630. },
  2631. {},
  2632. };
  2633. const int ruleset_fd =
  2634. create_ruleset(_metadata, rules[0].access, rules);
  2635. ASSERT_LE(0, ruleset_fd);
  2636. ASSERT_EQ(0, unlink(file1_s1d1));
  2637. ASSERT_EQ(0, unlink(file2_s1d1));
  2638. ASSERT_EQ(0, symlink("none", file2_s1d1));
  2639. ASSERT_EQ(0, unlink(file1_s1d2));
  2640. ASSERT_EQ(0, unlink(file2_s1d2));
  2641. ASSERT_EQ(0, unlink(file1_s1d3));
  2642. ASSERT_EQ(0, unlink(file2_s1d3));
  2643. enforce_ruleset(_metadata, ruleset_fd);
  2644. ASSERT_EQ(0, close(ruleset_fd));
  2645. ASSERT_EQ(-1, symlink("none", file1_s1d1));
  2646. ASSERT_EQ(EACCES, errno);
  2647. ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
  2648. ASSERT_EQ(EACCES, errno);
  2649. ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
  2650. ASSERT_EQ(EACCES, errno);
  2651. ASSERT_EQ(0, symlink("none", file1_s1d2));
  2652. ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
  2653. ASSERT_EQ(0, unlink(file2_s1d2));
  2654. ASSERT_EQ(0, rename(file1_s1d2, file2_s1d2));
  2655. ASSERT_EQ(0, symlink("none", file1_s1d3));
  2656. ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
  2657. ASSERT_EQ(0, unlink(file2_s1d3));
  2658. ASSERT_EQ(0, rename(file1_s1d3, file2_s1d3));
  2659. }
  2660. TEST_F_FORK(layout1, make_dir)
  2661. {
  2662. const struct rule rules[] = {
  2663. {
  2664. .path = dir_s1d2,
  2665. .access = LANDLOCK_ACCESS_FS_MAKE_DIR,
  2666. },
  2667. {},
  2668. };
  2669. const int ruleset_fd =
  2670. create_ruleset(_metadata, rules[0].access, rules);
  2671. ASSERT_LE(0, ruleset_fd);
  2672. ASSERT_EQ(0, unlink(file1_s1d1));
  2673. ASSERT_EQ(0, unlink(file1_s1d2));
  2674. ASSERT_EQ(0, unlink(file1_s1d3));
  2675. enforce_ruleset(_metadata, ruleset_fd);
  2676. ASSERT_EQ(0, close(ruleset_fd));
  2677. /* Uses file_* as directory names. */
  2678. ASSERT_EQ(-1, mkdir(file1_s1d1, 0700));
  2679. ASSERT_EQ(EACCES, errno);
  2680. ASSERT_EQ(0, mkdir(file1_s1d2, 0700));
  2681. ASSERT_EQ(0, mkdir(file1_s1d3, 0700));
  2682. }
  2683. static int open_proc_fd(struct __test_metadata *const _metadata, const int fd,
  2684. const int open_flags)
  2685. {
  2686. static const char path_template[] = "/proc/self/fd/%d";
  2687. char procfd_path[sizeof(path_template) + 10];
  2688. const int procfd_path_size =
  2689. snprintf(procfd_path, sizeof(procfd_path), path_template, fd);
  2690. ASSERT_LT(procfd_path_size, sizeof(procfd_path));
  2691. return open(procfd_path, open_flags);
  2692. }
  2693. TEST_F_FORK(layout1, proc_unlinked_file)
  2694. {
  2695. const struct rule rules[] = {
  2696. {
  2697. .path = file1_s1d2,
  2698. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  2699. },
  2700. {},
  2701. };
  2702. int reg_fd, proc_fd;
  2703. const int ruleset_fd = create_ruleset(
  2704. _metadata,
  2705. LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE,
  2706. rules);
  2707. ASSERT_LE(0, ruleset_fd);
  2708. enforce_ruleset(_metadata, ruleset_fd);
  2709. ASSERT_EQ(0, close(ruleset_fd));
  2710. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
  2711. ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
  2712. reg_fd = open(file1_s1d2, O_RDONLY | O_CLOEXEC);
  2713. ASSERT_LE(0, reg_fd);
  2714. ASSERT_EQ(0, unlink(file1_s1d2));
  2715. proc_fd = open_proc_fd(_metadata, reg_fd, O_RDONLY | O_CLOEXEC);
  2716. ASSERT_LE(0, proc_fd);
  2717. ASSERT_EQ(0, close(proc_fd));
  2718. proc_fd = open_proc_fd(_metadata, reg_fd, O_RDWR | O_CLOEXEC);
  2719. ASSERT_EQ(-1, proc_fd)
  2720. {
  2721. TH_LOG("Successfully opened /proc/self/fd/%d: %s", reg_fd,
  2722. strerror(errno));
  2723. }
  2724. ASSERT_EQ(EACCES, errno);
  2725. ASSERT_EQ(0, close(reg_fd));
  2726. }
  2727. TEST_F_FORK(layout1, proc_pipe)
  2728. {
  2729. int proc_fd;
  2730. int pipe_fds[2];
  2731. char buf = '\0';
  2732. const struct rule rules[] = {
  2733. {
  2734. .path = dir_s1d2,
  2735. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  2736. LANDLOCK_ACCESS_FS_WRITE_FILE,
  2737. },
  2738. {},
  2739. };
  2740. /* Limits read and write access to files tied to the filesystem. */
  2741. const int ruleset_fd =
  2742. create_ruleset(_metadata, rules[0].access, rules);
  2743. ASSERT_LE(0, ruleset_fd);
  2744. enforce_ruleset(_metadata, ruleset_fd);
  2745. ASSERT_EQ(0, close(ruleset_fd));
  2746. /* Checks enforcement for normal files. */
  2747. ASSERT_EQ(0, test_open(file1_s1d2, O_RDWR));
  2748. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
  2749. /* Checks access to pipes through FD. */
  2750. ASSERT_EQ(0, pipe2(pipe_fds, O_CLOEXEC));
  2751. ASSERT_EQ(1, write(pipe_fds[1], ".", 1))
  2752. {
  2753. TH_LOG("Failed to write in pipe: %s", strerror(errno));
  2754. }
  2755. ASSERT_EQ(1, read(pipe_fds[0], &buf, 1));
  2756. ASSERT_EQ('.', buf);
  2757. /* Checks write access to pipe through /proc/self/fd . */
  2758. proc_fd = open_proc_fd(_metadata, pipe_fds[1], O_WRONLY | O_CLOEXEC);
  2759. ASSERT_LE(0, proc_fd);
  2760. ASSERT_EQ(1, write(proc_fd, ".", 1))
  2761. {
  2762. TH_LOG("Failed to write through /proc/self/fd/%d: %s",
  2763. pipe_fds[1], strerror(errno));
  2764. }
  2765. ASSERT_EQ(0, close(proc_fd));
  2766. /* Checks read access to pipe through /proc/self/fd . */
  2767. proc_fd = open_proc_fd(_metadata, pipe_fds[0], O_RDONLY | O_CLOEXEC);
  2768. ASSERT_LE(0, proc_fd);
  2769. buf = '\0';
  2770. ASSERT_EQ(1, read(proc_fd, &buf, 1))
  2771. {
  2772. TH_LOG("Failed to read through /proc/self/fd/%d: %s",
  2773. pipe_fds[1], strerror(errno));
  2774. }
  2775. ASSERT_EQ(0, close(proc_fd));
  2776. ASSERT_EQ(0, close(pipe_fds[0]));
  2777. ASSERT_EQ(0, close(pipe_fds[1]));
  2778. }
  2779. /* clang-format off */
  2780. FIXTURE(layout1_bind) {};
  2781. /* clang-format on */
  2782. FIXTURE_SETUP(layout1_bind)
  2783. {
  2784. prepare_layout(_metadata);
  2785. create_layout1(_metadata);
  2786. set_cap(_metadata, CAP_SYS_ADMIN);
  2787. ASSERT_EQ(0, mount(dir_s1d2, dir_s2d2, NULL, MS_BIND, NULL));
  2788. clear_cap(_metadata, CAP_SYS_ADMIN);
  2789. }
  2790. FIXTURE_TEARDOWN(layout1_bind)
  2791. {
  2792. set_cap(_metadata, CAP_SYS_ADMIN);
  2793. EXPECT_EQ(0, umount(dir_s2d2));
  2794. clear_cap(_metadata, CAP_SYS_ADMIN);
  2795. remove_layout1(_metadata);
  2796. cleanup_layout(_metadata);
  2797. }
  2798. static const char bind_dir_s1d3[] = TMP_DIR "/s2d1/s2d2/s1d3";
  2799. static const char bind_file1_s1d3[] = TMP_DIR "/s2d1/s2d2/s1d3/f1";
  2800. /*
  2801. * layout1_bind hierarchy:
  2802. *
  2803. * tmp
  2804. * ├── s1d1
  2805. * │   ├── f1
  2806. * │   ├── f2
  2807. * │   └── s1d2
  2808. * │   ├── f1
  2809. * │   ├── f2
  2810. * │   └── s1d3
  2811. * │   ├── f1
  2812. * │   └── f2
  2813. * ├── s2d1
  2814. * │   ├── f1
  2815. * │   └── s2d2
  2816. * │   ├── f1
  2817. * │   ├── f2
  2818. * │   └── s1d3
  2819. * │   ├── f1
  2820. * │   └── f2
  2821. * └── s3d1
  2822. * └── s3d2
  2823. * └── s3d3
  2824. */
  2825. TEST_F_FORK(layout1_bind, no_restriction)
  2826. {
  2827. ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY));
  2828. ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
  2829. ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
  2830. ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
  2831. ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
  2832. ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
  2833. ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY));
  2834. ASSERT_EQ(0, test_open(file1_s2d1, O_RDONLY));
  2835. ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY));
  2836. ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
  2837. ASSERT_EQ(ENOENT, test_open(dir_s2d3, O_RDONLY));
  2838. ASSERT_EQ(ENOENT, test_open(file1_s2d3, O_RDONLY));
  2839. ASSERT_EQ(0, test_open(bind_dir_s1d3, O_RDONLY));
  2840. ASSERT_EQ(0, test_open(bind_file1_s1d3, O_RDONLY));
  2841. ASSERT_EQ(0, test_open(dir_s3d1, O_RDONLY));
  2842. }
  2843. TEST_F_FORK(layout1_bind, same_content_same_file)
  2844. {
  2845. /*
  2846. * Sets access right on parent directories of both source and
  2847. * destination mount points.
  2848. */
  2849. const struct rule layer1_parent[] = {
  2850. {
  2851. .path = dir_s1d1,
  2852. .access = ACCESS_RO,
  2853. },
  2854. {
  2855. .path = dir_s2d1,
  2856. .access = ACCESS_RW,
  2857. },
  2858. {},
  2859. };
  2860. /*
  2861. * Sets access rights on the same bind-mounted directories. The result
  2862. * should be ACCESS_RW for both directories, but not both hierarchies
  2863. * because of the first layer.
  2864. */
  2865. const struct rule layer2_mount_point[] = {
  2866. {
  2867. .path = dir_s1d2,
  2868. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  2869. },
  2870. {
  2871. .path = dir_s2d2,
  2872. .access = ACCESS_RW,
  2873. },
  2874. {},
  2875. };
  2876. /* Only allow read-access to the s1d3 hierarchies. */
  2877. const struct rule layer3_source[] = {
  2878. {
  2879. .path = dir_s1d3,
  2880. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  2881. },
  2882. {},
  2883. };
  2884. /* Removes all access rights. */
  2885. const struct rule layer4_destination[] = {
  2886. {
  2887. .path = bind_file1_s1d3,
  2888. .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
  2889. },
  2890. {},
  2891. };
  2892. int ruleset_fd;
  2893. /* Sets rules for the parent directories. */
  2894. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_parent);
  2895. ASSERT_LE(0, ruleset_fd);
  2896. enforce_ruleset(_metadata, ruleset_fd);
  2897. ASSERT_EQ(0, close(ruleset_fd));
  2898. /* Checks source hierarchy. */
  2899. ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY));
  2900. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
  2901. ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  2902. ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
  2903. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
  2904. ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
  2905. /* Checks destination hierarchy. */
  2906. ASSERT_EQ(0, test_open(file1_s2d1, O_RDWR));
  2907. ASSERT_EQ(0, test_open(dir_s2d1, O_RDONLY | O_DIRECTORY));
  2908. ASSERT_EQ(0, test_open(file1_s2d2, O_RDWR));
  2909. ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
  2910. /* Sets rules for the mount points. */
  2911. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_mount_point);
  2912. ASSERT_LE(0, ruleset_fd);
  2913. enforce_ruleset(_metadata, ruleset_fd);
  2914. ASSERT_EQ(0, close(ruleset_fd));
  2915. /* Checks source hierarchy. */
  2916. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
  2917. ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
  2918. ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
  2919. ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
  2920. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
  2921. ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
  2922. /* Checks destination hierarchy. */
  2923. ASSERT_EQ(EACCES, test_open(file1_s2d1, O_RDONLY));
  2924. ASSERT_EQ(EACCES, test_open(file1_s2d1, O_WRONLY));
  2925. ASSERT_EQ(EACCES, test_open(dir_s2d1, O_RDONLY | O_DIRECTORY));
  2926. ASSERT_EQ(0, test_open(file1_s2d2, O_RDWR));
  2927. ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
  2928. ASSERT_EQ(0, test_open(bind_dir_s1d3, O_RDONLY | O_DIRECTORY));
  2929. /* Sets a (shared) rule only on the source. */
  2930. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3_source);
  2931. ASSERT_LE(0, ruleset_fd);
  2932. enforce_ruleset(_metadata, ruleset_fd);
  2933. ASSERT_EQ(0, close(ruleset_fd));
  2934. /* Checks source hierarchy. */
  2935. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDONLY));
  2936. ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
  2937. ASSERT_EQ(EACCES, test_open(dir_s1d2, O_RDONLY | O_DIRECTORY));
  2938. ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
  2939. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
  2940. ASSERT_EQ(EACCES, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
  2941. /* Checks destination hierarchy. */
  2942. ASSERT_EQ(EACCES, test_open(file1_s2d2, O_RDONLY));
  2943. ASSERT_EQ(EACCES, test_open(file1_s2d2, O_WRONLY));
  2944. ASSERT_EQ(EACCES, test_open(dir_s2d2, O_RDONLY | O_DIRECTORY));
  2945. ASSERT_EQ(0, test_open(bind_file1_s1d3, O_RDONLY));
  2946. ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_WRONLY));
  2947. ASSERT_EQ(EACCES, test_open(bind_dir_s1d3, O_RDONLY | O_DIRECTORY));
  2948. /* Sets a (shared) rule only on the destination. */
  2949. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer4_destination);
  2950. ASSERT_LE(0, ruleset_fd);
  2951. enforce_ruleset(_metadata, ruleset_fd);
  2952. ASSERT_EQ(0, close(ruleset_fd));
  2953. /* Checks source hierarchy. */
  2954. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
  2955. ASSERT_EQ(EACCES, test_open(file1_s1d3, O_WRONLY));
  2956. /* Checks destination hierarchy. */
  2957. ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_RDONLY));
  2958. ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_WRONLY));
  2959. }
  2960. TEST_F_FORK(layout1_bind, reparent_cross_mount)
  2961. {
  2962. const struct rule layer1[] = {
  2963. {
  2964. /* dir_s2d1 is beneath the dir_s2d2 mount point. */
  2965. .path = dir_s2d1,
  2966. .access = LANDLOCK_ACCESS_FS_REFER,
  2967. },
  2968. {
  2969. .path = bind_dir_s1d3,
  2970. .access = LANDLOCK_ACCESS_FS_EXECUTE,
  2971. },
  2972. {},
  2973. };
  2974. int ruleset_fd = create_ruleset(
  2975. _metadata,
  2976. LANDLOCK_ACCESS_FS_REFER | LANDLOCK_ACCESS_FS_EXECUTE, layer1);
  2977. ASSERT_LE(0, ruleset_fd);
  2978. enforce_ruleset(_metadata, ruleset_fd);
  2979. ASSERT_EQ(0, close(ruleset_fd));
  2980. /* Checks basic denied move. */
  2981. ASSERT_EQ(-1, rename(file1_s1d1, file1_s1d2));
  2982. ASSERT_EQ(EXDEV, errno);
  2983. /* Checks real cross-mount move (Landlock is not involved). */
  2984. ASSERT_EQ(-1, rename(file1_s2d1, file1_s2d2));
  2985. ASSERT_EQ(EXDEV, errno);
  2986. /* Checks move that will give more accesses. */
  2987. ASSERT_EQ(-1, rename(file1_s2d2, bind_file1_s1d3));
  2988. ASSERT_EQ(EXDEV, errno);
  2989. /* Checks legitimate downgrade move. */
  2990. ASSERT_EQ(0, rename(bind_file1_s1d3, file1_s2d2));
  2991. }
  2992. #define LOWER_BASE TMP_DIR "/lower"
  2993. #define LOWER_DATA LOWER_BASE "/data"
  2994. static const char lower_fl1[] = LOWER_DATA "/fl1";
  2995. static const char lower_dl1[] = LOWER_DATA "/dl1";
  2996. static const char lower_dl1_fl2[] = LOWER_DATA "/dl1/fl2";
  2997. static const char lower_fo1[] = LOWER_DATA "/fo1";
  2998. static const char lower_do1[] = LOWER_DATA "/do1";
  2999. static const char lower_do1_fo2[] = LOWER_DATA "/do1/fo2";
  3000. static const char lower_do1_fl3[] = LOWER_DATA "/do1/fl3";
  3001. static const char (*lower_base_files[])[] = {
  3002. &lower_fl1,
  3003. &lower_fo1,
  3004. NULL,
  3005. };
  3006. static const char (*lower_base_directories[])[] = {
  3007. &lower_dl1,
  3008. &lower_do1,
  3009. NULL,
  3010. };
  3011. static const char (*lower_sub_files[])[] = {
  3012. &lower_dl1_fl2,
  3013. &lower_do1_fo2,
  3014. &lower_do1_fl3,
  3015. NULL,
  3016. };
  3017. #define UPPER_BASE TMP_DIR "/upper"
  3018. #define UPPER_DATA UPPER_BASE "/data"
  3019. #define UPPER_WORK UPPER_BASE "/work"
  3020. static const char upper_fu1[] = UPPER_DATA "/fu1";
  3021. static const char upper_du1[] = UPPER_DATA "/du1";
  3022. static const char upper_du1_fu2[] = UPPER_DATA "/du1/fu2";
  3023. static const char upper_fo1[] = UPPER_DATA "/fo1";
  3024. static const char upper_do1[] = UPPER_DATA "/do1";
  3025. static const char upper_do1_fo2[] = UPPER_DATA "/do1/fo2";
  3026. static const char upper_do1_fu3[] = UPPER_DATA "/do1/fu3";
  3027. static const char (*upper_base_files[])[] = {
  3028. &upper_fu1,
  3029. &upper_fo1,
  3030. NULL,
  3031. };
  3032. static const char (*upper_base_directories[])[] = {
  3033. &upper_du1,
  3034. &upper_do1,
  3035. NULL,
  3036. };
  3037. static const char (*upper_sub_files[])[] = {
  3038. &upper_du1_fu2,
  3039. &upper_do1_fo2,
  3040. &upper_do1_fu3,
  3041. NULL,
  3042. };
  3043. #define MERGE_BASE TMP_DIR "/merge"
  3044. #define MERGE_DATA MERGE_BASE "/data"
  3045. static const char merge_fl1[] = MERGE_DATA "/fl1";
  3046. static const char merge_dl1[] = MERGE_DATA "/dl1";
  3047. static const char merge_dl1_fl2[] = MERGE_DATA "/dl1/fl2";
  3048. static const char merge_fu1[] = MERGE_DATA "/fu1";
  3049. static const char merge_du1[] = MERGE_DATA "/du1";
  3050. static const char merge_du1_fu2[] = MERGE_DATA "/du1/fu2";
  3051. static const char merge_fo1[] = MERGE_DATA "/fo1";
  3052. static const char merge_do1[] = MERGE_DATA "/do1";
  3053. static const char merge_do1_fo2[] = MERGE_DATA "/do1/fo2";
  3054. static const char merge_do1_fl3[] = MERGE_DATA "/do1/fl3";
  3055. static const char merge_do1_fu3[] = MERGE_DATA "/do1/fu3";
  3056. static const char (*merge_base_files[])[] = {
  3057. &merge_fl1,
  3058. &merge_fu1,
  3059. &merge_fo1,
  3060. NULL,
  3061. };
  3062. static const char (*merge_base_directories[])[] = {
  3063. &merge_dl1,
  3064. &merge_du1,
  3065. &merge_do1,
  3066. NULL,
  3067. };
  3068. static const char (*merge_sub_files[])[] = {
  3069. &merge_dl1_fl2, &merge_du1_fu2, &merge_do1_fo2,
  3070. &merge_do1_fl3, &merge_do1_fu3, NULL,
  3071. };
  3072. /*
  3073. * layout2_overlay hierarchy:
  3074. *
  3075. * tmp
  3076. * ├── lower
  3077. * │   └── data
  3078. * │   ├── dl1
  3079. * │   │   └── fl2
  3080. * │   ├── do1
  3081. * │   │   ├── fl3
  3082. * │   │   └── fo2
  3083. * │   ├── fl1
  3084. * │   └── fo1
  3085. * ├── merge
  3086. * │   └── data
  3087. * │   ├── dl1
  3088. * │   │   └── fl2
  3089. * │   ├── do1
  3090. * │   │   ├── fl3
  3091. * │   │   ├── fo2
  3092. * │   │   └── fu3
  3093. * │   ├── du1
  3094. * │   │   └── fu2
  3095. * │   ├── fl1
  3096. * │   ├── fo1
  3097. * │   └── fu1
  3098. * └── upper
  3099. * ├── data
  3100. * │   ├── do1
  3101. * │   │   ├── fo2
  3102. * │   │   └── fu3
  3103. * │   ├── du1
  3104. * │   │   └── fu2
  3105. * │   ├── fo1
  3106. * │   └── fu1
  3107. * └── work
  3108. * └── work
  3109. */
  3110. /* clang-format off */
  3111. FIXTURE(layout2_overlay) {};
  3112. /* clang-format on */
  3113. FIXTURE_SETUP(layout2_overlay)
  3114. {
  3115. if (!supports_overlayfs())
  3116. SKIP(return, "overlayfs is not supported");
  3117. prepare_layout(_metadata);
  3118. create_directory(_metadata, LOWER_BASE);
  3119. set_cap(_metadata, CAP_SYS_ADMIN);
  3120. /* Creates tmpfs mount points to get deterministic overlayfs. */
  3121. ASSERT_EQ(0, mount("tmp", LOWER_BASE, "tmpfs", 0, "size=4m,mode=700"));
  3122. clear_cap(_metadata, CAP_SYS_ADMIN);
  3123. create_file(_metadata, lower_fl1);
  3124. create_file(_metadata, lower_dl1_fl2);
  3125. create_file(_metadata, lower_fo1);
  3126. create_file(_metadata, lower_do1_fo2);
  3127. create_file(_metadata, lower_do1_fl3);
  3128. create_directory(_metadata, UPPER_BASE);
  3129. set_cap(_metadata, CAP_SYS_ADMIN);
  3130. ASSERT_EQ(0, mount("tmp", UPPER_BASE, "tmpfs", 0, "size=4m,mode=700"));
  3131. clear_cap(_metadata, CAP_SYS_ADMIN);
  3132. create_file(_metadata, upper_fu1);
  3133. create_file(_metadata, upper_du1_fu2);
  3134. create_file(_metadata, upper_fo1);
  3135. create_file(_metadata, upper_do1_fo2);
  3136. create_file(_metadata, upper_do1_fu3);
  3137. ASSERT_EQ(0, mkdir(UPPER_WORK, 0700));
  3138. create_directory(_metadata, MERGE_DATA);
  3139. set_cap(_metadata, CAP_SYS_ADMIN);
  3140. set_cap(_metadata, CAP_DAC_OVERRIDE);
  3141. ASSERT_EQ(0, mount("overlay", MERGE_DATA, "overlay", 0,
  3142. "lowerdir=" LOWER_DATA ",upperdir=" UPPER_DATA
  3143. ",workdir=" UPPER_WORK));
  3144. clear_cap(_metadata, CAP_DAC_OVERRIDE);
  3145. clear_cap(_metadata, CAP_SYS_ADMIN);
  3146. }
  3147. FIXTURE_TEARDOWN(layout2_overlay)
  3148. {
  3149. if (!supports_overlayfs())
  3150. SKIP(return, "overlayfs is not supported");
  3151. EXPECT_EQ(0, remove_path(lower_do1_fl3));
  3152. EXPECT_EQ(0, remove_path(lower_dl1_fl2));
  3153. EXPECT_EQ(0, remove_path(lower_fl1));
  3154. EXPECT_EQ(0, remove_path(lower_do1_fo2));
  3155. EXPECT_EQ(0, remove_path(lower_fo1));
  3156. set_cap(_metadata, CAP_SYS_ADMIN);
  3157. EXPECT_EQ(0, umount(LOWER_BASE));
  3158. clear_cap(_metadata, CAP_SYS_ADMIN);
  3159. EXPECT_EQ(0, remove_path(LOWER_BASE));
  3160. EXPECT_EQ(0, remove_path(upper_do1_fu3));
  3161. EXPECT_EQ(0, remove_path(upper_du1_fu2));
  3162. EXPECT_EQ(0, remove_path(upper_fu1));
  3163. EXPECT_EQ(0, remove_path(upper_do1_fo2));
  3164. EXPECT_EQ(0, remove_path(upper_fo1));
  3165. EXPECT_EQ(0, remove_path(UPPER_WORK "/work"));
  3166. set_cap(_metadata, CAP_SYS_ADMIN);
  3167. EXPECT_EQ(0, umount(UPPER_BASE));
  3168. clear_cap(_metadata, CAP_SYS_ADMIN);
  3169. EXPECT_EQ(0, remove_path(UPPER_BASE));
  3170. set_cap(_metadata, CAP_SYS_ADMIN);
  3171. EXPECT_EQ(0, umount(MERGE_DATA));
  3172. clear_cap(_metadata, CAP_SYS_ADMIN);
  3173. EXPECT_EQ(0, remove_path(MERGE_DATA));
  3174. cleanup_layout(_metadata);
  3175. }
  3176. TEST_F_FORK(layout2_overlay, no_restriction)
  3177. {
  3178. if (!supports_overlayfs())
  3179. SKIP(return, "overlayfs is not supported");
  3180. ASSERT_EQ(0, test_open(lower_fl1, O_RDONLY));
  3181. ASSERT_EQ(0, test_open(lower_dl1, O_RDONLY));
  3182. ASSERT_EQ(0, test_open(lower_dl1_fl2, O_RDONLY));
  3183. ASSERT_EQ(0, test_open(lower_fo1, O_RDONLY));
  3184. ASSERT_EQ(0, test_open(lower_do1, O_RDONLY));
  3185. ASSERT_EQ(0, test_open(lower_do1_fo2, O_RDONLY));
  3186. ASSERT_EQ(0, test_open(lower_do1_fl3, O_RDONLY));
  3187. ASSERT_EQ(0, test_open(upper_fu1, O_RDONLY));
  3188. ASSERT_EQ(0, test_open(upper_du1, O_RDONLY));
  3189. ASSERT_EQ(0, test_open(upper_du1_fu2, O_RDONLY));
  3190. ASSERT_EQ(0, test_open(upper_fo1, O_RDONLY));
  3191. ASSERT_EQ(0, test_open(upper_do1, O_RDONLY));
  3192. ASSERT_EQ(0, test_open(upper_do1_fo2, O_RDONLY));
  3193. ASSERT_EQ(0, test_open(upper_do1_fu3, O_RDONLY));
  3194. ASSERT_EQ(0, test_open(merge_fl1, O_RDONLY));
  3195. ASSERT_EQ(0, test_open(merge_dl1, O_RDONLY));
  3196. ASSERT_EQ(0, test_open(merge_dl1_fl2, O_RDONLY));
  3197. ASSERT_EQ(0, test_open(merge_fu1, O_RDONLY));
  3198. ASSERT_EQ(0, test_open(merge_du1, O_RDONLY));
  3199. ASSERT_EQ(0, test_open(merge_du1_fu2, O_RDONLY));
  3200. ASSERT_EQ(0, test_open(merge_fo1, O_RDONLY));
  3201. ASSERT_EQ(0, test_open(merge_do1, O_RDONLY));
  3202. ASSERT_EQ(0, test_open(merge_do1_fo2, O_RDONLY));
  3203. ASSERT_EQ(0, test_open(merge_do1_fl3, O_RDONLY));
  3204. ASSERT_EQ(0, test_open(merge_do1_fu3, O_RDONLY));
  3205. }
  3206. #define for_each_path(path_list, path_entry, i) \
  3207. for (i = 0, path_entry = *path_list[i]; path_list[i]; \
  3208. path_entry = *path_list[++i])
  3209. TEST_F_FORK(layout2_overlay, same_content_different_file)
  3210. {
  3211. /* Sets access right on parent directories of both layers. */
  3212. const struct rule layer1_base[] = {
  3213. {
  3214. .path = LOWER_BASE,
  3215. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3216. },
  3217. {
  3218. .path = UPPER_BASE,
  3219. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3220. },
  3221. {
  3222. .path = MERGE_BASE,
  3223. .access = ACCESS_RW,
  3224. },
  3225. {},
  3226. };
  3227. const struct rule layer2_data[] = {
  3228. {
  3229. .path = LOWER_DATA,
  3230. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3231. },
  3232. {
  3233. .path = UPPER_DATA,
  3234. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3235. },
  3236. {
  3237. .path = MERGE_DATA,
  3238. .access = ACCESS_RW,
  3239. },
  3240. {},
  3241. };
  3242. /* Sets access right on directories inside both layers. */
  3243. const struct rule layer3_subdirs[] = {
  3244. {
  3245. .path = lower_dl1,
  3246. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3247. },
  3248. {
  3249. .path = lower_do1,
  3250. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3251. },
  3252. {
  3253. .path = upper_du1,
  3254. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3255. },
  3256. {
  3257. .path = upper_do1,
  3258. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3259. },
  3260. {
  3261. .path = merge_dl1,
  3262. .access = ACCESS_RW,
  3263. },
  3264. {
  3265. .path = merge_du1,
  3266. .access = ACCESS_RW,
  3267. },
  3268. {
  3269. .path = merge_do1,
  3270. .access = ACCESS_RW,
  3271. },
  3272. {},
  3273. };
  3274. /* Tighten access rights to the files. */
  3275. const struct rule layer4_files[] = {
  3276. {
  3277. .path = lower_dl1_fl2,
  3278. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3279. },
  3280. {
  3281. .path = lower_do1_fo2,
  3282. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3283. },
  3284. {
  3285. .path = lower_do1_fl3,
  3286. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3287. },
  3288. {
  3289. .path = upper_du1_fu2,
  3290. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3291. },
  3292. {
  3293. .path = upper_do1_fo2,
  3294. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3295. },
  3296. {
  3297. .path = upper_do1_fu3,
  3298. .access = LANDLOCK_ACCESS_FS_READ_FILE,
  3299. },
  3300. {
  3301. .path = merge_dl1_fl2,
  3302. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  3303. LANDLOCK_ACCESS_FS_WRITE_FILE,
  3304. },
  3305. {
  3306. .path = merge_du1_fu2,
  3307. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  3308. LANDLOCK_ACCESS_FS_WRITE_FILE,
  3309. },
  3310. {
  3311. .path = merge_do1_fo2,
  3312. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  3313. LANDLOCK_ACCESS_FS_WRITE_FILE,
  3314. },
  3315. {
  3316. .path = merge_do1_fl3,
  3317. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  3318. LANDLOCK_ACCESS_FS_WRITE_FILE,
  3319. },
  3320. {
  3321. .path = merge_do1_fu3,
  3322. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  3323. LANDLOCK_ACCESS_FS_WRITE_FILE,
  3324. },
  3325. {},
  3326. };
  3327. const struct rule layer5_merge_only[] = {
  3328. {
  3329. .path = MERGE_DATA,
  3330. .access = LANDLOCK_ACCESS_FS_READ_FILE |
  3331. LANDLOCK_ACCESS_FS_WRITE_FILE,
  3332. },
  3333. {},
  3334. };
  3335. int ruleset_fd;
  3336. size_t i;
  3337. const char *path_entry;
  3338. if (!supports_overlayfs())
  3339. SKIP(return, "overlayfs is not supported");
  3340. /* Sets rules on base directories (i.e. outside overlay scope). */
  3341. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1_base);
  3342. ASSERT_LE(0, ruleset_fd);
  3343. enforce_ruleset(_metadata, ruleset_fd);
  3344. ASSERT_EQ(0, close(ruleset_fd));
  3345. /* Checks lower layer. */
  3346. for_each_path(lower_base_files, path_entry, i) {
  3347. ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
  3348. ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
  3349. }
  3350. for_each_path(lower_base_directories, path_entry, i) {
  3351. ASSERT_EQ(EACCES,
  3352. test_open(path_entry, O_RDONLY | O_DIRECTORY));
  3353. }
  3354. for_each_path(lower_sub_files, path_entry, i) {
  3355. ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
  3356. ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
  3357. }
  3358. /* Checks upper layer. */
  3359. for_each_path(upper_base_files, path_entry, i) {
  3360. ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
  3361. ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
  3362. }
  3363. for_each_path(upper_base_directories, path_entry, i) {
  3364. ASSERT_EQ(EACCES,
  3365. test_open(path_entry, O_RDONLY | O_DIRECTORY));
  3366. }
  3367. for_each_path(upper_sub_files, path_entry, i) {
  3368. ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
  3369. ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
  3370. }
  3371. /*
  3372. * Checks that access rights are independent from the lower and upper
  3373. * layers: write access to upper files viewed through the merge point
  3374. * is still allowed, and write access to lower file viewed (and copied)
  3375. * through the merge point is still allowed.
  3376. */
  3377. for_each_path(merge_base_files, path_entry, i) {
  3378. ASSERT_EQ(0, test_open(path_entry, O_RDWR));
  3379. }
  3380. for_each_path(merge_base_directories, path_entry, i) {
  3381. ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
  3382. }
  3383. for_each_path(merge_sub_files, path_entry, i) {
  3384. ASSERT_EQ(0, test_open(path_entry, O_RDWR));
  3385. }
  3386. /* Sets rules on data directories (i.e. inside overlay scope). */
  3387. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2_data);
  3388. ASSERT_LE(0, ruleset_fd);
  3389. enforce_ruleset(_metadata, ruleset_fd);
  3390. ASSERT_EQ(0, close(ruleset_fd));
  3391. /* Checks merge. */
  3392. for_each_path(merge_base_files, path_entry, i) {
  3393. ASSERT_EQ(0, test_open(path_entry, O_RDWR));
  3394. }
  3395. for_each_path(merge_base_directories, path_entry, i) {
  3396. ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
  3397. }
  3398. for_each_path(merge_sub_files, path_entry, i) {
  3399. ASSERT_EQ(0, test_open(path_entry, O_RDWR));
  3400. }
  3401. /* Same checks with tighter rules. */
  3402. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3_subdirs);
  3403. ASSERT_LE(0, ruleset_fd);
  3404. enforce_ruleset(_metadata, ruleset_fd);
  3405. ASSERT_EQ(0, close(ruleset_fd));
  3406. /* Checks changes for lower layer. */
  3407. for_each_path(lower_base_files, path_entry, i) {
  3408. ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
  3409. }
  3410. /* Checks changes for upper layer. */
  3411. for_each_path(upper_base_files, path_entry, i) {
  3412. ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
  3413. }
  3414. /* Checks all merge accesses. */
  3415. for_each_path(merge_base_files, path_entry, i) {
  3416. ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
  3417. }
  3418. for_each_path(merge_base_directories, path_entry, i) {
  3419. ASSERT_EQ(0, test_open(path_entry, O_RDONLY | O_DIRECTORY));
  3420. }
  3421. for_each_path(merge_sub_files, path_entry, i) {
  3422. ASSERT_EQ(0, test_open(path_entry, O_RDWR));
  3423. }
  3424. /* Sets rules directly on overlayed files. */
  3425. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer4_files);
  3426. ASSERT_LE(0, ruleset_fd);
  3427. enforce_ruleset(_metadata, ruleset_fd);
  3428. ASSERT_EQ(0, close(ruleset_fd));
  3429. /* Checks unchanged accesses on lower layer. */
  3430. for_each_path(lower_sub_files, path_entry, i) {
  3431. ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
  3432. ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
  3433. }
  3434. /* Checks unchanged accesses on upper layer. */
  3435. for_each_path(upper_sub_files, path_entry, i) {
  3436. ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
  3437. ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
  3438. }
  3439. /* Checks all merge accesses. */
  3440. for_each_path(merge_base_files, path_entry, i) {
  3441. ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
  3442. }
  3443. for_each_path(merge_base_directories, path_entry, i) {
  3444. ASSERT_EQ(EACCES,
  3445. test_open(path_entry, O_RDONLY | O_DIRECTORY));
  3446. }
  3447. for_each_path(merge_sub_files, path_entry, i) {
  3448. ASSERT_EQ(0, test_open(path_entry, O_RDWR));
  3449. }
  3450. /* Only allowes access to the merge hierarchy. */
  3451. ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer5_merge_only);
  3452. ASSERT_LE(0, ruleset_fd);
  3453. enforce_ruleset(_metadata, ruleset_fd);
  3454. ASSERT_EQ(0, close(ruleset_fd));
  3455. /* Checks new accesses on lower layer. */
  3456. for_each_path(lower_sub_files, path_entry, i) {
  3457. ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
  3458. }
  3459. /* Checks new accesses on upper layer. */
  3460. for_each_path(upper_sub_files, path_entry, i) {
  3461. ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY));
  3462. }
  3463. /* Checks all merge accesses. */
  3464. for_each_path(merge_base_files, path_entry, i) {
  3465. ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
  3466. }
  3467. for_each_path(merge_base_directories, path_entry, i) {
  3468. ASSERT_EQ(EACCES,
  3469. test_open(path_entry, O_RDONLY | O_DIRECTORY));
  3470. }
  3471. for_each_path(merge_sub_files, path_entry, i) {
  3472. ASSERT_EQ(0, test_open(path_entry, O_RDWR));
  3473. }
  3474. }
  3475. TEST_HARNESS_MAIN