• Aurelien Aptel's avatar
    cifs: fix rename() by ensuring source handle opened with DELETE bit · 86f740f2
    Aurelien Aptel authored
    To rename a file in SMB2 we open it with the DELETE access and do a
    special SetInfo on it. If the handle is missing the DELETE bit the
    server will fail the SetInfo with STATUS_ACCESS_DENIED.
    
    We currently try to reuse any existing opened handle we have with
    cifs_get_writable_path(). That function looks for handles with WRITE
    access but doesn't check for DELETE, making rename() fail if it finds
    a handle to reuse. Simple reproducer below.
    
    To select handles with the DELETE bit, this patch adds a flag argument
    to cifs_get_writable_path() and find_writable_file() and the existing
    'bool fsuid_only' argument is converted to a flag.
    
    The cifsFileInfo struct only stores the UNIX open mode but not the
    original SMB access flags. Since the DELETE bit is not mapped in that
    mode, this patch stores the access mask in cifs_fid on file open,
    which is accessible from cifsFileInfo.
    
    Simple reproducer:
    
    	#include <stdio.h>
    	#include <stdlib.h>
    	#include <sys/types.h>
    	#include <sys/stat.h>
    	#include <fcntl.h>
    	#include <unistd.h>
    	#define E(s) perror(s), exit(1)
    
    	int main(int argc, char *argv[])
    	{
    		int fd, ret;
    		if (argc != 3) {
    			fprintf(stderr, "Usage: %s A B\n"
    			"create&open A in write mode, "
    			"rename A to B, close A\n", argv[0]);
    			return 0;
    		}
    
    		fd = openat(AT_FDCWD, argv[1], O_WRONLY|O_CREAT|O_SYNC, 0666);
    		if (fd == -1) E("openat()");
    
    		ret = rename(argv[1], argv[2]);
    		if (ret) E("rename()");
    
    		ret = close(fd);
    		if (ret) E("close()");
    
    		return ret;
    	}
    
    $ gcc -o bugrename bugrename.c
    $ ./bugrename /mnt/a /mnt/b
    rename(): Permission denied
    
    Fixes: 8de9e86c ("cifs: create a helper to find a writeable handle by path name")
    CC: Stable <stable@vger.kernel.org>
    Signed-off-by: default avatarAurelien Aptel <aaptel@suse.com>
    Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
    Reviewed-by: default avatarPavel Shilovsky <pshilov@microsoft.com>
    Reviewed-by: default avatarPaulo Alcantara (SUSE) <pc@cjr.nz>
    86f740f2
cifsproto.h 27.7 KB