lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <2d735cb666872099b2c4c574e35aaeac2f7356ad.camel@gmail.com>
Date:   Mon, 01 Jun 2020 21:58:36 +0200
From:   Jakob Unterwurzacher <jakobunt@...il.com>
To:     linux-cifs@...r.kernel.org
Cc:     linux-kernel@...r.kernel.org
Subject: cifs vs Go: EINTR and ENOENT errors from getdents64

Hi, author of gocryptfs here, an encrypted overlay
filesystem written in Go.

A gocryptfs user reported [1] hitting EINTR errors
when gocryptfs is used on a cifs mount.

I wrote a minimal reproducer, getdents.go [2], that runs
getdents64 in a loop and I can reproduce the issue easily.
I additionally see ENOENT errors.

The errors can also be seen via the high-level Readdirnames()
function that the Go stdlib provides [6].

I am running kernel 5.6.13 and Samba 4.12.2 for this test.
I have a cifs share mounted as shown in [3], populated
with 1001 empty files using

    touch $(seq 1000 2000)

. When running getdents.go [2] against this mount, good cases look
like this (output from getdents.go):

    --- example 0 ---

    unix.Getdents: n=4176; n=4176; n=4176; n=4176; n=4176; n=3192; n=0; err=<nil>; total 24072 bytes
    unix.Getdents: n=4176; n=4176; n=4176; n=4176; n=24; n=4152; n=3192; n=0; err=<nil>; total 24072 bytes


INTR errors look like this (getdents.go output and corresponding
kernel debug messages that were enabled acc. to [4]):

    --- example 1 ---

    unix.Getdents: n=-1; err=interrupted system call; total 0 bytes

    [168340.499471] fs/cifs/file.c: CIFS VFS: leaving cifs_closedir (xid = 24238) rc = 0
    [168340.599686] fs/cifs/readdir.c: Full path:  start at: 0
    [168340.599696] fs/cifs/transport.c: signal is pending before sending any data
    [168340.599698] smb2_add_credits: 310 callbacks suppressed
    [168340.599699] fs/cifs/smb2ops.c: add 1 credits total=8192
    [168340.599701] fs/cifs/smb2ops.c: query_dir_first: open failed rc=-4
    [168340.599702] fs/cifs/readdir.c: initiate cifs search rc -4
    [168340.599979] fs/cifs/file.c: Closedir inode = 0x0000000067f9a79c
    [168340.599981] fs/cifs/file.c: CIFS VFS: in cifs_closedir as Xid: 24240 with uid: 1026
    [168340.599982] fs/cifs/file.c: Freeing private data in close dir
    [168340.599983] fs/cifs/file.c: CIFS VFS: leaving cifs_closedir (xid = 24240) rc = 0

    --- example 2 ---

    unix.Getdents: n=-1; err=interrupted system call; total 0 bytes

    [168453.792894] Status code returned 0x80000006 STATUS_NO_MORE_FILES
    [168453.893360] fs/cifs/transport.c: signal is pending before sending any data
    [168453.893363] fs/cifs/smb2ops.c: query_dir_first: open failed rc=-4


ENOENT errors look like this:

    --- example 3 ---

    unix.Getdents: n=4176; n=4176; n=4176; n=4176; n=4176; n=-1; err=no such file or directory; total 20880 bytes

    [168517.187072] Status code returned 0x80000006 STATUS_NO_MORE_FILES
    [168517.300252] fs/cifs/transport.c: signal is pending before sending any data
    [168517.300255] fs/cifs/readdir.c: fce error -2

    --- example 4 ---

    unix.Getdents: n=4176; n=4176; n=4176; n=1440; n=2736; n=-1; err=no such file or directory; total 16704 bytes

    [168650.603145] Status code returned 0x80000006 STATUS_NO_MORE_FILES
    [168650.713831] fs/cifs/transport.c: signal is pending before sending any data
    [168650.713835] fs/cifs/readdir.c: fce error -2


I have the same thing written in C does not show
any problems [5].

The Go runtime uses signals heavily, could this be a
reason for the behavoir I am seeing? I can trigger
the problem more quickly when I resize the terminal
window (causing SIGWINCH). Note that the Go runtime
sets SA_RESTART on all signal handlers.

I can handle the EINTR errors by retrying, no problem.
Should I also retry when I get ENOENT?

Thanks,
Jakob


[1] https://github.com/rfjakob/gocryptfs/issues/483
[2] https://github.com/rfjakob/gocryptfs/blob/master/contrib/getdents-debug/getdents/getdents.go
[3] //127.0.0.1/samba-test on /mnt/samba-test type cifs
(rw,relatime,vers=3.1.1,cache=strict,username=jakob,uid=1026,forceuid,gid=1026,forcegid,addr=127.0.0.1,file_mode=0755,dir_mode=0755,soft,nounix,serverino,mappos
ix,rsize=4194304,wsize=4194304,bsize=1048576,echo_interval=60,actimeo=1,user=jakob)
[4] https://wiki.samba.org/index.php/LinuxCIFS_troubleshooting#Enabling_Debugging
[5] https://github.com/rfjakob/gocryptfs/blob/master/contrib/getdents-debug/getdents_c/getdents.c
[6] https://github.com/golang/go/issues/39237

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ