Bug 15142 - File listings fail without owner read permission when built without O_PATH
Summary: File listings fail without owner read permission when built without O_PATH
Status: RESOLVED INVALID
Alias: None
Product: Samba 4.1 and newer
Classification: Unclassified
Component: File services (show other bugs)
Version: unspecified
Hardware: All All
: P5 normal (vote)
Target Milestone: ---
Assignee: Jeremy Allison
QA Contact: Samba QA Contact
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-08-10 16:33 UTC by David Mulder
Modified: 2022-08-15 20:11 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description David Mulder 2022-08-10 16:33:39 UTC
When Samba master (pre 4.18) is configured without O_PATH, file listings (smb2 query directory) will fail if the file posix permissions do not include owner read permissions. This became obvious when testing the SMB3 posix patches, since I could create/open/delete a file without owner read, but then couldn't list it. This does not happen when built with O_PATH.

It's easy to reproduce:

ADDITIONAL_CFLAGS='-DDISABLE_OPATH=1' ./configure.developer --without-ad-dc && SELFTEST_TESTENV=fileserver make testenv


In a different terminal, change directory to the share and create a file without owner read permissions:

dmulder@dmlaptop:~/code/samba> cd st/fileserver/share
dmulder@dmlaptop:~/code/samba/st/fileserver/share> rm -rf *
dmulder@dmlaptop:~/code/samba/st/fileserver/share> touch test
dmulder@dmlaptop:~/code/samba/st/fileserver/share> chmod u-r test
dmulder@dmlaptop:~/code/samba/st/fileserver/share> l
total 136K
drwxrwxrwx  2 dmulder 132K Aug 10 10:30 ./
drwxrwxrwx 12 dmulder 4.0K Aug 10 10:20 ../
--w-r--r--  1 dmulder    0 Aug 10 10:30 test

Within the testenv:

dmulder@fileserver:~/code/samba> ./bin/smbclient -s $SMB_CONF_PATH \\\\$SERVER_IP\\tmpPassword for [WORKGROUP\dmulder]:
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Wed Aug 10 16:30:05 2022
  ..                                  D        0  Wed Aug 10 16:20:19 2022

                1921725720 blocks of size 1024. 1224130300 blocks available
smb: \> 

In your other terminal, give the test file owner read permissions again:

dmulder@dmlaptop:~/code/samba/st/fileserver/share> chmod u+r test
dmulder@dmlaptop:~/code/samba/st/fileserver/share> l
total 136K
drwxrwxrwx  2 dmulder 132K Aug 10 10:30 ./
drwxrwxrwx 12 dmulder 4.0K Aug 10 10:20 ../
-rw-r--r--  1 dmulder    0 Aug 10 10:30 test

And in the testenv:

smb: \> ls
  .                                   D        0  Wed Aug 10 16:30:05 2022
  ..                                  D        0  Wed Aug 10 16:20:19 2022
  test                                N        0  Wed Aug 10 16:30:05 2022

                1921725720 blocks of size 1024. 1224128856 blocks available
smb: \> 

Testing the same scenario when built with O_PATH always lists the test file.
Comment 1 Jeremy Allison 2022-08-11 19:12:25 UTC
OK, log here shows (for file JRATEST) with no O_PATH:

openat_pathref_fullname: fsp [..]: OK
file_free: freed files structure 0 (1 used)
smbd_dirptr_get_entry mask=[*] found .. fname=.. (..)
smbd_marshall_dir_entry: space_remaining = 8388488
smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO
smbd_dirptr_get_entry: dir [.] dirptr [0x5603dc87eb10] offset [9188369107692161392] => dname [JRATEST]
openat_pathref_fsp: smb_fname [JRATEST]
openat_pathref_fullname: smb_fname [JRATEST]
fsp_new: allocated files structure (2 used)
file_name_hash: /home/jeremy/src/samba/git/metze/st/fileserver/share/JRATEST hash 0x16409c1a
push_sec_ctx(1000, 1000) : sec_ctx_stack_ndx = 1
push_conn_ctx(682576849) : conn_ctx_stack_ndx = 0
setting sec ctx (0, 0) - sec_ctx_stack_ndx = 1
Security token: (NULL)
UNIX token of user 0
Primary group is 0 and contains 0 supplementary groups
pop_sec_ctx (1000, 1000) - sec_ctx_stack_ndx = 0
fd_openat: name JRATEST, flags = 04000 mode = 00, fd = -1. NT_STATUS_ACCESS_DENIED
openat_pathref_fullname: Opening pathref for [JRATEST] failed: NT_STATUS_ACCESS_DENIED
Comment 2 Jeremy Allison 2022-08-11 19:31:05 UTC
David, does this happen in real-world cases other than our test environment ?

I added a DEBUG that shows that for test file JRATEST:

vfswrap_openat: JRATEST: vfswrap_openat: have_opath = 0, is_pathref = 1

and then I see:

push_sec_ctx(1000, 1000) : sec_ctx_stack_ndx = 1
push_conn_ctx(390295636) : conn_ctx_stack_ndx = 0
setting sec ctx (0, 0) - sec_ctx_stack_ndx = 1
Security token: (NULL)
UNIX token of user 0
Primary group is 0 and contains 0 supplementary groups
pop_sec_ctx (1000, 1000) - sec_ctx_stack_ndx = 0

before the call to:

fd_openat: name JRATEST, flags = 04000 mode = 00, fd = -1. NT_STATUS_ACCESS_DENIED

I think this is an artifact of the test environment, in that when we're running under testenv we have no access to real root - we just fake it.

So if the real underlying filesystem has a file with u-r removed, then under the test env we can never get to it, even if we've done a become_root().

Try and reproduce this with the -DDISABLE_OPATH=1 build running for real, and I think you'll find we still access the u-r file.

I think you might have to fix your test to cope with this.
Comment 3 David Mulder 2022-08-11 19:35:18 UTC
(In reply to Jeremy Allison from comment #2)
Ah, that makes sense. I've only seen it in the test environment. I've already modified the tests to avoid this issue, so we can simply close this bug.
Comment 4 David Mulder 2022-08-11 20:34:48 UTC
I just confirmed that this does work as expected outside the samba test environment.
Comment 5 Stefan Metzmacher 2022-08-14 23:34:41 UTC
(In reply to Jeremy Allison from comment #2)

I also hit this with this commit:

https://gitlab.com/samba-team/samba/-/merge_requests/2669/diffs?commit_id=573ab934ead73fc01d10a88d5ab4b3fa492e7994

So we need to add this to selftest/skip.opath-required where
we already have a "These fail because become_root() doesn't work in make test"
section? Or better have a selftest/knownfail.opath-required?
Comment 6 Jeremy Allison 2022-08-15 16:46:52 UTC
My preference would be for a selftest/knownfail.opath-required, but I'll leave it up to you :-).
Comment 7 David Mulder 2022-08-15 18:15:34 UTC
(In reply to Jeremy Allison from comment #6)

I agree, but I didn't know we could do a knownfail for specific environments. Is this something that needs implemented, or does this already work?
Comment 8 Stefan Metzmacher 2022-08-15 20:11:59 UTC
(In reply to David Mulder from comment #7)

--- a/selftest/wscript
+++ b/selftest/wscript
@@ -280,6 +280,7 @@ def cmd_testonly(opt):
 
     if os.environ.get('DISABLE_OPATH'):
         env.OPTIONS += " --exclude=${srcdir}/selftest/skip.opath-required"
+        env.FILTER_XFAIL += " --expected-failures=${srcdir}/selftest/knownfail.opath-required"
 
     if env.ADDRESS_SANITIZER:
         # We try to find the correct libasan automatically

But first the backbox tests need to support knownfail for individual subtests...