1 1.14 riastrad /* $NetBSD: t_pr.c,v 1.14 2025/04/13 02:10:30 riastradh Exp $ */ 2 1.1 pooka 3 1.1 pooka #include <sys/types.h> 4 1.1 pooka #include <sys/mount.h> 5 1.1 pooka 6 1.1 pooka #include <atf-c.h> 7 1.1 pooka #include <err.h> 8 1.1 pooka #include <errno.h> 9 1.1 pooka #include <fcntl.h> 10 1.1 pooka #include <stdio.h> 11 1.1 pooka #include <unistd.h> 12 1.1 pooka #include <string.h> 13 1.1 pooka #include <stdlib.h> 14 1.1 pooka 15 1.1 pooka #include <rump/rump.h> 16 1.1 pooka #include <rump/rump_syscalls.h> 17 1.1 pooka 18 1.1 pooka #include <miscfs/union/union.h> 19 1.1 pooka 20 1.9 christos #include "h_macros.h" 21 1.1 pooka 22 1.1 pooka ATF_TC(multilayer); 23 1.1 pooka ATF_TC_HEAD(multilayer, tc) 24 1.1 pooka { 25 1.1 pooka atf_tc_set_md_var(tc, "descr", "mount_union -b twice"); 26 1.1 pooka } 27 1.1 pooka 28 1.1 pooka ATF_TC_BODY(multilayer, tc) 29 1.1 pooka { 30 1.1 pooka struct union_args unionargs; 31 1.1 pooka 32 1.1 pooka rump_init(); 33 1.1 pooka 34 1.1 pooka if (rump_sys_mkdir("/Tunion", 0777) == -1) 35 1.1 pooka atf_tc_fail_errno("mkdir mp1"); 36 1.1 pooka if (rump_sys_mkdir("/Tunion2", 0777) == -1) 37 1.1 pooka atf_tc_fail_errno("mkdir mp2"); 38 1.1 pooka if (rump_sys_mkdir("/Tunion2/A", 0777) == -1) 39 1.1 pooka atf_tc_fail_errno("mkdir A"); 40 1.1 pooka if (rump_sys_mkdir("/Tunion2/B", 0777) == -1) 41 1.1 pooka atf_tc_fail_errno("mkdir B"); 42 1.1 pooka 43 1.1 pooka unionargs.target = __UNCONST("/Tunion2/A"); 44 1.1 pooka unionargs.mntflags = UNMNT_BELOW; 45 1.1 pooka 46 1.1 pooka if (rump_sys_mount(MOUNT_UNION, "/Tunion", 0, 47 1.1 pooka &unionargs, sizeof(unionargs)) == -1) 48 1.1 pooka atf_tc_fail_errno("union mount"); 49 1.1 pooka 50 1.1 pooka unionargs.target = __UNCONST("/Tunion2/B"); 51 1.1 pooka unionargs.mntflags = UNMNT_BELOW; 52 1.1 pooka 53 1.1 pooka rump_sys_mount(MOUNT_UNION, "/Tunion", 0,&unionargs,sizeof(unionargs)); 54 1.1 pooka } 55 1.1 pooka 56 1.10 maya ATF_TC(multilayer2); 57 1.10 maya ATF_TC_HEAD(multilayer2, tc) 58 1.10 maya { 59 1.10 maya atf_tc_set_md_var(tc, "descr", "mount_union twice then unmount"); 60 1.10 maya } 61 1.10 maya 62 1.10 maya ATF_TC_BODY(multilayer2, tc) 63 1.10 maya { 64 1.10 maya struct union_args unionargs; 65 1.10 maya 66 1.12 riastrad atf_tc_expect_signal(-1, "PR kern/2423"); 67 1.11 riastrad 68 1.10 maya rump_init(); 69 1.10 maya 70 1.10 maya if (rump_sys_mkdir("/Tunion", 0777) == -1) 71 1.10 maya atf_tc_fail_errno("mkdir mp1"); 72 1.10 maya if (rump_sys_mkdir("/Tunion2", 0777) == -1) 73 1.10 maya atf_tc_fail_errno("mkdir mp2"); 74 1.10 maya if (rump_sys_mkdir("/Tunion2/A", 0777) == -1) 75 1.10 maya atf_tc_fail_errno("mkdir A"); 76 1.10 maya if (rump_sys_mkdir("/Tunion2/B", 0777) == -1) 77 1.10 maya atf_tc_fail_errno("mkdir B"); 78 1.10 maya 79 1.10 maya unionargs.target = __UNCONST("/Tunion2/A"); 80 1.10 maya unionargs.mntflags = UNMNT_ABOVE; 81 1.10 maya 82 1.10 maya if (rump_sys_mount(MOUNT_UNION, "/Tunion", 0, 83 1.10 maya &unionargs, sizeof(unionargs)) == -1) 84 1.10 maya atf_tc_fail_errno("union mount"); 85 1.10 maya if (rump_sys_mkdir("/Tunion2/A/A", 0777) == -1) 86 1.10 maya atf_tc_fail_errno("mkdir A/A"); 87 1.10 maya 88 1.10 maya unionargs.target = __UNCONST("/Tunion2/A/A"); 89 1.10 maya unionargs.mntflags = UNMNT_ABOVE; 90 1.10 maya 91 1.10 maya rump_sys_mount(MOUNT_UNION, "/Tunion", 0,&unionargs,sizeof(unionargs)); 92 1.10 maya 93 1.10 maya rump_sys_unmount("/Tunion/A", 0); 94 1.10 maya } 95 1.10 maya 96 1.10 maya ATF_TC(cyclic); 97 1.10 maya ATF_TC_HEAD(cyclic, tc) 98 1.10 maya { 99 1.10 maya atf_tc_set_md_var(tc, "descr", "cyclic mount_union"); 100 1.10 maya } 101 1.10 maya 102 1.10 maya ATF_TC_BODY(cyclic, tc) 103 1.10 maya { 104 1.10 maya struct union_args unionargs; 105 1.10 maya 106 1.12 riastrad atf_tc_expect_signal(-1, "PR kern/3645"); 107 1.11 riastrad 108 1.10 maya rump_init(); 109 1.10 maya 110 1.10 maya if (rump_sys_mkdir("/Tunion", 0777) == -1) 111 1.10 maya atf_tc_fail_errno("mkdir mp1"); 112 1.10 maya if (rump_sys_mkdir("/Tunion/A", 0777) == -1) 113 1.10 maya atf_tc_fail_errno("mkdir mp2"); 114 1.10 maya 115 1.10 maya unionargs.target = __UNCONST("/Tunion/A"); 116 1.10 maya unionargs.mntflags = UNMNT_ABOVE; 117 1.10 maya 118 1.10 maya if (rump_sys_mount(MOUNT_UNION, "/Tunion/A", 0, 119 1.10 maya &unionargs, sizeof(unionargs)) == -1) 120 1.10 maya atf_tc_fail_errno("union mount"); 121 1.10 maya 122 1.10 maya if (rump_sys_mkdir("/Tunion/A/A", 0777) == -1) 123 1.10 maya atf_tc_fail_errno("mkdir failed"); 124 1.10 maya } 125 1.10 maya 126 1.10 maya ATF_TC(cyclic2); 127 1.10 maya ATF_TC_HEAD(cyclic2, tc) 128 1.10 maya { 129 1.10 maya atf_tc_set_md_var(tc, "descr", "cyclic mount_union"); 130 1.10 maya } 131 1.10 maya 132 1.10 maya ATF_TC_BODY(cyclic2, tc) 133 1.10 maya { 134 1.10 maya struct union_args unionargs; 135 1.10 maya 136 1.12 riastrad atf_tc_expect_signal(-1, "PR kern/4597"); 137 1.11 riastrad 138 1.10 maya rump_init(); 139 1.10 maya 140 1.10 maya if (rump_sys_mkdir("/Tunion", 0777) == -1) 141 1.10 maya atf_tc_fail_errno("mkdir mp1"); 142 1.10 maya if (rump_sys_mkdir("/Tunion/A", 0777) == -1) 143 1.10 maya atf_tc_fail_errno("mkdir mp2"); 144 1.10 maya if (rump_sys_mkdir("/Tunion/B", 0777) == -1) 145 1.10 maya atf_tc_fail_errno("mkdir mp3"); 146 1.10 maya 147 1.10 maya unionargs.target = __UNCONST("/Tunion/A"); 148 1.10 maya unionargs.mntflags = UNMNT_ABOVE; 149 1.10 maya 150 1.10 maya if (rump_sys_mount(MOUNT_UNION, "/Tunion/B", 0, 151 1.10 maya &unionargs, sizeof(unionargs)) == -1) 152 1.10 maya atf_tc_fail_errno("union mount"); 153 1.10 maya 154 1.10 maya unionargs.target = __UNCONST("/Tunion/B"); 155 1.10 maya unionargs.mntflags = UNMNT_ABOVE; 156 1.10 maya 157 1.10 maya if (rump_sys_mount(MOUNT_UNION, "/Tunion/A", 0, 158 1.10 maya &unionargs, sizeof(unionargs)) == -1) 159 1.10 maya atf_tc_fail_errno("union mount2"); 160 1.10 maya 161 1.10 maya if (rump_sys_mkdir("/Tunion/A/A", 0777) == -1) 162 1.10 maya atf_tc_fail_errno("mkdir failed"); 163 1.10 maya } 164 1.10 maya 165 1.4 pooka ATF_TC(devnull1); 166 1.4 pooka ATF_TC_HEAD(devnull1, tc) 167 1.4 pooka { 168 1.4 pooka atf_tc_set_md_var(tc, "descr", "mount_union -b and " 169 1.4 pooka "'echo x > /un/null'"); 170 1.4 pooka } 171 1.4 pooka 172 1.4 pooka ATF_TC_BODY(devnull1, tc) 173 1.4 pooka { 174 1.4 pooka struct union_args unionargs; 175 1.8 hannken int fd, res; 176 1.4 pooka 177 1.4 pooka rump_init(); 178 1.4 pooka 179 1.4 pooka if (rump_sys_mkdir("/mp", 0777) == -1) 180 1.4 pooka atf_tc_fail_errno("mkdir mp"); 181 1.4 pooka 182 1.4 pooka unionargs.target = __UNCONST("/dev"); 183 1.4 pooka unionargs.mntflags = UNMNT_BELOW; 184 1.4 pooka 185 1.4 pooka if (rump_sys_mount(MOUNT_UNION, "/mp", 0, 186 1.4 pooka &unionargs, sizeof(unionargs)) == -1) 187 1.4 pooka atf_tc_fail_errno("union mount"); 188 1.4 pooka 189 1.13 martin fd = rump_sys_open("/mp/null", O_WRONLY | O_CREAT | O_TRUNC, 0600); 190 1.4 pooka 191 1.8 hannken if (fd == -1) 192 1.8 hannken atf_tc_fail_errno("open"); 193 1.6 pooka 194 1.8 hannken res = rump_sys_write(fd, &fd, sizeof(fd)); 195 1.8 hannken if (res != sizeof(fd)) 196 1.8 hannken atf_tc_fail("write"); 197 1.4 pooka } 198 1.4 pooka 199 1.4 pooka ATF_TC(devnull2); 200 1.4 pooka ATF_TC_HEAD(devnull2, tc) 201 1.4 pooka { 202 1.4 pooka atf_tc_set_md_var(tc, "descr", "mount_union -b and " 203 1.4 pooka "'echo x >> /un/null'"); 204 1.4 pooka } 205 1.4 pooka 206 1.4 pooka ATF_TC_BODY(devnull2, tc) 207 1.4 pooka { 208 1.4 pooka struct union_args unionargs; 209 1.8 hannken int fd, res; 210 1.4 pooka 211 1.4 pooka rump_init(); 212 1.4 pooka 213 1.4 pooka if (rump_sys_mkdir("/mp", 0777) == -1) 214 1.4 pooka atf_tc_fail_errno("mkdir mp"); 215 1.4 pooka 216 1.4 pooka unionargs.target = __UNCONST("/dev"); 217 1.4 pooka unionargs.mntflags = UNMNT_BELOW; 218 1.4 pooka 219 1.4 pooka if (rump_sys_mount(MOUNT_UNION, "/mp", 0, 220 1.4 pooka &unionargs, sizeof(unionargs)) == -1) 221 1.4 pooka atf_tc_fail_errno("union mount"); 222 1.4 pooka 223 1.13 martin fd = rump_sys_open("/mp/null", O_WRONLY | O_CREAT | O_APPEND, 0600); 224 1.4 pooka if (fd == -1) 225 1.4 pooka atf_tc_fail_errno("open"); 226 1.4 pooka 227 1.8 hannken res = rump_sys_write(fd, &fd, sizeof(fd)); 228 1.8 hannken if (res != sizeof(fd)) 229 1.8 hannken atf_tc_fail("write"); 230 1.4 pooka } 231 1.4 pooka 232 1.14 riastrad ATF_TC(pr1677_lowerunsearchabledot); 233 1.14 riastrad ATF_TC_HEAD(pr1677_lowerunsearchabledot, tc) 234 1.14 riastrad { 235 1.14 riastrad atf_tc_set_md_var(tc, "descr", 236 1.14 riastrad "Lookup of `.' when searchable in upper, unsearchable in lower"); 237 1.14 riastrad } 238 1.14 riastrad 239 1.14 riastrad ATF_TC_BODY(pr1677_lowerunsearchabledot, tc) 240 1.14 riastrad { 241 1.14 riastrad struct union_args unionargs; 242 1.14 riastrad struct stat sb; 243 1.14 riastrad 244 1.14 riastrad rump_init(); 245 1.14 riastrad 246 1.14 riastrad RL(rump_sys_mkdir("/lower", 0777)); 247 1.14 riastrad RL(rump_sys_mkdir("/lower/foo", 0700)); /* restricted */ 248 1.14 riastrad 249 1.14 riastrad RL(rump_sys_mkdir("/upper", 0777)); 250 1.14 riastrad RL(rump_sys_mkdir("/upper/foo", 0777)); 251 1.14 riastrad 252 1.14 riastrad memset(&unionargs, 0, sizeof(unionargs)); 253 1.14 riastrad unionargs.target = __UNCONST("/upper"); 254 1.14 riastrad unionargs.mntflags = UNMNT_ABOVE; 255 1.14 riastrad RL(rump_sys_mount(MOUNT_UNION, "/lower", 0, 256 1.14 riastrad &unionargs, sizeof(unionargs))); 257 1.14 riastrad 258 1.14 riastrad /* pretend we're an unprivileged process */ 259 1.14 riastrad rump_pub_lwproc_rfork(RUMP_RFCFDG); 260 1.14 riastrad RL(rump_sys_setgid(1)); 261 1.14 riastrad RL(rump_sys_setegid(1)); 262 1.14 riastrad RL(rump_sys_setuid(32767)); 263 1.14 riastrad RL(rump_sys_seteuid(32767)); 264 1.14 riastrad atf_tc_expect_signal(SIGABRT, "PR kern/1677:" 265 1.14 riastrad " union FS can return bogus value for lookup of `.'," 266 1.14 riastrad " causing later panic"); 267 1.14 riastrad RL(rump_sys_lstat("/lower/foo/.", &sb)); 268 1.14 riastrad rump_pub_lwproc_releaselwp(); 269 1.14 riastrad } 270 1.14 riastrad 271 1.1 pooka ATF_TP_ADD_TCS(tp) 272 1.1 pooka { 273 1.1 pooka ATF_TP_ADD_TC(tp, multilayer); 274 1.10 maya ATF_TP_ADD_TC(tp, multilayer2); 275 1.10 maya ATF_TP_ADD_TC(tp, cyclic); 276 1.10 maya ATF_TP_ADD_TC(tp, cyclic2); 277 1.4 pooka ATF_TP_ADD_TC(tp, devnull1); 278 1.4 pooka ATF_TP_ADD_TC(tp, devnull2); 279 1.14 riastrad ATF_TP_ADD_TC(tp, pr1677_lowerunsearchabledot); 280 1.1 pooka 281 1.1 pooka return atf_no_error(); 282 1.1 pooka } 283