Home | History | Annotate | Line # | Download | only in c063
t_o_search.c revision 1.7
      1 /*	$NetBSD: t_o_search.c,v 1.7 2020/02/05 08:52:46 martin Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2012 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Emmanuel Dreyfus.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 #include <sys/cdefs.h>
     32 __RCSID("$NetBSD: t_o_search.c,v 1.7 2020/02/05 08:52:46 martin Exp $");
     33 
     34 #include <atf-c.h>
     35 
     36 #include <sys/param.h>
     37 #include <sys/stat.h>
     38 
     39 #include <errno.h>
     40 #include <fcntl.h>
     41 #include <limits.h>
     42 #include <paths.h>
     43 #include <stdio.h>
     44 #include <string.h>
     45 #include <unistd.h>
     46 #include <pwd.h>
     47 
     48 /*
     49  * dholland 20130112: disable tests that require O_SEARCH semantics
     50  * until a decision is reached about the semantics of O_SEARCH and a
     51  * non-broken implementation is available.
     52  */
     53 #if (O_MASK & O_SEARCH) != 0
     54 #define USE_O_SEARCH
     55 #endif
     56 
     57 #define DIR "dir"
     58 #define FILE "dir/o_search"
     59 #define BASEFILE "o_search"
     60 
     61 
     62 ATF_TC(o_search_perm1);
     63 ATF_TC_HEAD(o_search_perm1, tc)
     64 {
     65 	atf_tc_set_md_var(tc, "descr", "See that openat enforces search permission");
     66 	atf_tc_set_md_var(tc, "require.user", "unprivileged");
     67 }
     68 ATF_TC_BODY(o_search_perm1, tc)
     69 {
     70 	int dfd;
     71 	int fd;
     72 
     73 	ATF_REQUIRE(mkdir(DIR, 0755) == 0);
     74 	ATF_REQUIRE((fd = open(FILE, O_CREAT|O_RDWR, 0644)) != -1);
     75 	ATF_REQUIRE(close(fd) == 0);
     76 
     77 	ATF_REQUIRE((dfd = open(DIR, O_RDONLY, 0)) != -1);
     78 
     79 	ATF_REQUIRE((fd = openat(dfd, BASEFILE, O_RDWR, 0)) != -1);
     80 	ATF_REQUIRE(close(fd) == 0);
     81 
     82 	ATF_REQUIRE(fchmod(dfd, 0644) == 0);
     83 
     84 	ATF_REQUIRE((fd = openat(dfd, BASEFILE, O_RDWR, 0)) == -1);
     85 	ATF_REQUIRE(errno == EACCES);
     86 
     87 	ATF_REQUIRE(close(dfd) == 0);
     88 }
     89 
     90 #ifdef USE_O_SEARCH
     91 
     92 ATF_TC(o_search_root_flag1);
     93 ATF_TC_HEAD(o_search_root_flag1, tc)
     94 {
     95 	atf_tc_set_md_var(tc, "descr", "See that root openat honours O_SEARCH");
     96 	atf_tc_set_md_var(tc, "require.user", "root");
     97 }
     98 ATF_TC_BODY(o_search_root_flag1, tc)
     99 {
    100 	int dfd;
    101 	int fd;
    102 
    103 	ATF_REQUIRE(mkdir(DIR, 0755) == 0);
    104 	ATF_REQUIRE((fd = open(FILE, O_CREAT|O_RDWR, 0644)) != -1);
    105 	ATF_REQUIRE(close(fd) == 0);
    106 
    107 	ATF_REQUIRE((dfd = open(DIR, O_RDONLY|O_SEARCH, 0)) != -1);
    108 
    109 	ATF_REQUIRE((fd = openat(dfd, BASEFILE, O_RDWR, 0)) != -1);
    110 	ATF_REQUIRE(close(fd) == 0);
    111 
    112 	ATF_REQUIRE(fchmod(dfd, 0644) == 0);
    113 
    114 	ATF_REQUIRE((fd = openat(dfd, BASEFILE, O_RDWR, 0)) != -1);
    115 	ATF_REQUIRE(close(fd) == 0);
    116 
    117 	ATF_REQUIRE(fchmod(dfd, 0444) == 0);
    118 
    119 	ATF_REQUIRE((fd = openat(dfd, BASEFILE, O_RDWR, 0)) != -1);
    120 
    121 	ATF_REQUIRE(close(dfd) == 0);
    122 }
    123 
    124 ATF_TC(o_search_unpriv_flag1);
    125 ATF_TC_HEAD(o_search_unpriv_flag1, tc)
    126 {
    127 	atf_tc_set_md_var(tc, "descr", "See that openat honours O_SEARCH");
    128 	atf_tc_set_md_var(tc, "require.user", "unprivileged");
    129 }
    130 ATF_TC_BODY(o_search_unpriv_flag1, tc)
    131 {
    132 	int dfd;
    133 	int fd;
    134 
    135 	ATF_REQUIRE(mkdir(DIR, 0755) == 0);
    136 	ATF_REQUIRE((fd = open(FILE, O_CREAT|O_RDWR, 0644)) != -1);
    137 	ATF_REQUIRE(close(fd) == 0);
    138 
    139 	ATF_REQUIRE((dfd = open(DIR, O_RDONLY|O_SEARCH, 0)) != -1);
    140 
    141 	ATF_REQUIRE((fd = openat(dfd, BASEFILE, O_RDWR, 0)) != -1);
    142 	ATF_REQUIRE(close(fd) == 0);
    143 
    144 	ATF_REQUIRE(fchmod(dfd, 0644) == 0);
    145 
    146 	ATF_REQUIRE((fd = openat(dfd, BASEFILE, O_RDWR, 0)) != -1);
    147 	ATF_REQUIRE(close(fd) == 0);
    148 
    149 	ATF_REQUIRE(fchmod(dfd, 0444) == 0);
    150 
    151 	ATF_REQUIRE((fd = openat(dfd, BASEFILE, O_RDWR, 0)) != -1);
    152 
    153 	ATF_REQUIRE(close(dfd) == 0);
    154 }
    155 
    156 #endif /* USE_O_SEARCH */
    157 
    158 ATF_TC(o_search_perm2);
    159 ATF_TC_HEAD(o_search_perm2, tc)
    160 {
    161 	atf_tc_set_md_var(tc, "descr", "See that faccessat enforces search permission");
    162 	atf_tc_set_md_var(tc, "require.user", "unprivileged");
    163 }
    164 ATF_TC_BODY(o_search_perm2, tc)
    165 {
    166 	int dfd;
    167 	int fd;
    168 	ATF_REQUIRE(mkdir(DIR, 0755) == 0);
    169 	ATF_REQUIRE((fd = open(FILE, O_CREAT|O_RDWR, 0644)) != -1);
    170 	ATF_REQUIRE(close(fd) == 0);
    171 
    172 	ATF_REQUIRE((dfd = open(DIR, O_RDONLY, 0)) != -1);
    173 
    174 	ATF_REQUIRE(faccessat(dfd, BASEFILE, W_OK, 0) == 0);
    175 
    176 	ATF_REQUIRE(fchmod(dfd, 0644) == 0);
    177 
    178 	ATF_REQUIRE(faccessat(dfd, BASEFILE, W_OK, 0) == -1);
    179 	ATF_REQUIRE(errno == EACCES);
    180 
    181 	ATF_REQUIRE(close(dfd) == 0);
    182 }
    183 
    184 #ifdef USE_O_SEARCH
    185 
    186 ATF_TC(o_search_root_flag2);
    187 ATF_TC_HEAD(o_search_root_flag2, tc)
    188 {
    189 	atf_tc_set_md_var(tc, "descr", "See that root fstatat honours O_SEARCH");
    190 	atf_tc_set_md_var(tc, "require.user", "root");
    191 }
    192 ATF_TC_BODY(o_search_root_flag2, tc)
    193 {
    194 	int dfd;
    195 	int fd;
    196 
    197 	ATF_REQUIRE(mkdir(DIR, 0755) == 0);
    198 	ATF_REQUIRE((fd = open(FILE, O_CREAT|O_RDWR, 0644)) != -1);
    199 	ATF_REQUIRE(close(fd) == 0);
    200 
    201 	ATF_REQUIRE((dfd = open(DIR, O_RDONLY|O_SEARCH, 0)) != -1);
    202 
    203 	ATF_REQUIRE(faccessat(dfd, BASEFILE, W_OK, 0) == 0);
    204 
    205 	ATF_REQUIRE(fchmod(dfd, 0644) == 0);
    206 
    207 	ATF_REQUIRE(faccessat(dfd, BASEFILE, W_OK, 0) == 0);
    208 
    209 	ATF_REQUIRE(fchmod(dfd, 0444) == 0);
    210 
    211 	ATF_REQUIRE(faccessat(dfd, BASEFILE, W_OK, 0) == 0);
    212 
    213 	ATF_REQUIRE(close(dfd) == 0);
    214 }
    215 
    216 ATF_TC(o_search_unpriv_flag2);
    217 ATF_TC_HEAD(o_search_unpriv_flag2, tc)
    218 {
    219 	atf_tc_set_md_var(tc, "descr", "See that fstatat honours O_SEARCH");
    220 	atf_tc_set_md_var(tc, "require.user", "unprivileged");
    221 }
    222 ATF_TC_BODY(o_search_unpriv_flag2, tc)
    223 {
    224 	int dfd;
    225 	int fd;
    226 
    227 	ATF_REQUIRE(mkdir(DIR, 0755) == 0);
    228 	ATF_REQUIRE((fd = open(FILE, O_CREAT|O_RDWR, 0644)) != -1);
    229 	ATF_REQUIRE(close(fd) == 0);
    230 
    231 	ATF_REQUIRE((dfd = open(DIR, O_RDONLY|O_SEARCH, 0)) != -1);
    232 
    233 	ATF_REQUIRE(faccessat(dfd, BASEFILE, W_OK, 0) == 0);
    234 
    235 	ATF_REQUIRE(fchmod(dfd, 0644) == 0);
    236 
    237 	ATF_REQUIRE(faccessat(dfd, BASEFILE, W_OK, 0) == 0);
    238 
    239 	ATF_REQUIRE(fchmod(dfd, 0444) == 0);
    240 
    241 	ATF_REQUIRE(faccessat(dfd, BASEFILE, W_OK, 0) == 0);
    242 
    243 	ATF_REQUIRE(close(dfd) == 0);
    244 }
    245 
    246 #endif /* USE_O_SEARCH */
    247 
    248 
    249 ATF_TC(o_search_notdir);
    250 ATF_TC_HEAD(o_search_notdir, tc)
    251 {
    252 	atf_tc_set_md_var(tc, "descr", "See that openat fails with non dir fd");
    253 }
    254 ATF_TC_BODY(o_search_notdir, tc)
    255 {
    256 	int dfd;
    257 	int fd;
    258 
    259 	ATF_REQUIRE(mkdir(DIR, 0755) == 0);
    260 	ATF_REQUIRE((dfd = open(FILE, O_CREAT|O_RDWR|O_SEARCH, 0644)) != -1);
    261 	ATF_REQUIRE((fd = openat(dfd, BASEFILE, O_RDWR, 0)) == -1);
    262 	ATF_REQUIRE(errno == ENOTDIR);
    263 	ATF_REQUIRE(close(dfd) == 0);
    264 }
    265 
    266 ATF_TP_ADD_TCS(tp)
    267 {
    268 
    269 	ATF_TP_ADD_TC(tp, o_search_perm1);
    270 #ifdef USE_O_SEARCH
    271 	ATF_TP_ADD_TC(tp, o_search_root_flag1);
    272 	ATF_TP_ADD_TC(tp, o_search_unpriv_flag1);
    273 #endif
    274 	ATF_TP_ADD_TC(tp, o_search_perm2);
    275 #ifdef USE_O_SEARCH
    276 	ATF_TP_ADD_TC(tp, o_search_root_flag2);
    277 	ATF_TP_ADD_TC(tp, o_search_unpriv_flag2);
    278 #endif
    279 	ATF_TP_ADD_TC(tp, o_search_notdir);
    280 
    281 	return atf_no_error();
    282 }
    283