Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp1800961imm; Tue, 10 Jul 2018 08:07:12 -0700 (PDT) X-Google-Smtp-Source: AAOMgpeheEv1/+uyRqsnJDoVtHxPA9FLxlT8hcYCGDFHaL9QpdNQVfKtDUUqTB9imtpeXfZ5zeFt X-Received: by 2002:a62:998:: with SMTP id 24-v6mr24161530pfj.99.1531235232698; Tue, 10 Jul 2018 08:07:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531235232; cv=none; d=google.com; s=arc-20160816; b=NzuEn9RNflO9y3p/svyDF5o44YnIGVcPeYPTeCjO23TqGGVCaVC2mRqQVQL6wOI8I1 iPKvxKrZkhe+TfGCiB+WR+c/fOu4C8tKfw2u4ZI9JLNZ8OysoBSferVKJIvEaqve52A8 Txrj4n9EuilXk6+b0larPiLCu5zhkSTILzHT88P3i2BvEInK2N6GJVuQMR4uh7MTa7T4 u8UPqBUwg8V9ybzKkHfNSKPMB7GNW4beOLXHUxvYswT7bnCuiqnd96OXRLG1uLXsU83D rlsGXrsCpcGieKfS0i6H1ewUJA1YEAcbspgeQ9dWW28nlRtkIRMptv39BhV+WgwqTzId RPiw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:arc-authentication-results; bh=YBluRcUin3DO9ftfo7vh6sGwKaY23PArwStF3CR82Ig=; b=v7HG1AnUXpY5eIBp0MXL2yMN128r+TolJNSXBX1k3Q93Ai8DdTgiLDX84wye4F3wWt YPdoszt3tT1+b9xtysQ2IcqManhchWPZ5Qle17qmr3SgMx5lF4/19j3BFmZ1/HVocOsJ O7rx1s4THi/xdlBXXI1kfIGT8cCbIBin0xeiCdGXoDqGeW+k+BiBExMLuL1CBIEHBzZA k1KNlPq5f+tMYpVBtciwDByrwZkWUc5y28Eb6h9gySs+PmRIusHhkJNqJG60JIf98Fg9 k4ZdGqxhT4DVaJyFR6P0vHRBC/hAXWvYueq4LbxFhpdBYnRuPrAiVjuhO/GKEUX64HyY G8Ww== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t137-v6si16566078pgb.528.2018.07.10.08.06.43; Tue, 10 Jul 2018 08:07:12 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933808AbeGJPE7 (ORCPT + 99 others); Tue, 10 Jul 2018 11:04:59 -0400 Received: from zeniv.linux.org.uk ([195.92.253.2]:55950 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933324AbeGJPE6 (ORCPT ); Tue, 10 Jul 2018 11:04:58 -0400 Received: from viro by ZenIV.linux.org.uk with local (Exim 4.87 #1 (Red Hat Linux)) id 1fcuCF-0005lH-A7; Tue, 10 Jul 2018 15:04:55 +0000 Date: Tue, 10 Jul 2018 16:04:55 +0100 From: Al Viro To: Stephen Rothwell Cc: Miklos Szeredi , Linux-Next Mailing List , Linux Kernel Mailing List Subject: Re: linux-next: manual merge of the vfs tree with the overlayfs tree Message-ID: <20180710150455.GK30522@ZenIV.linux.org.uk> References: <20180710101736.32d6cc6c@canb.auug.org.au> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20180710101736.32d6cc6c@canb.auug.org.au> User-Agent: Mutt/1.9.1 (2017-09-22) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Jul 10, 2018 at 10:17:36AM +1000, Stephen Rothwell wrote: > --- a/fs/open.c > +++ b/fs/open.c > @@@ -731,7 -732,6 +721,7 @@@ static int do_dentry_open(struct file * > static const struct file_operations empty_fops = {}; > int error; > > - WARN_ON(f->f_mode & ~FMODE_NOACCOUNT); > ++ WARN_ON(f->f_mode & ~ (FMODE_NOACCOUNT | FMODE_CREATED)); > f->f_mode |= OPEN_FMODE(f->f_flags) | FMODE_LSEEK | > FMODE_PREAD | FMODE_PWRITE; That part is sane > +/** > + * path_open() - Open an inode by a particular name. > + * @path: The name of the file. > + * @flags: The O_ flags used to open this file. > + * @inode: The inode to open. > + * @cred: The task's credentials used when opening this file. > + * > + * Context: Process context. > + * Return: A pointer to a struct file or an IS_ERR pointer. Cannot return NULL. > + */ > +struct file *path_open(const struct path *path, int flags, struct inode *inode, > + const struct cred *cred, bool account) > +{ > + struct file *file; > + int error; > + > + file = __get_empty_filp(account); > + if (IS_ERR(file)) > + return file; > > + file->f_flags = flags; > file->f_path = *path; > - return do_dentry_open(file, d_backing_inode(dentry), NULL, cred); > + error = do_dentry_open(file, inode, NULL, cred); > + if (error) { > - put_filp(file); > ++ if (file->f_mode & FMODE_OPENED) > ++ fput(file); > ++ else > ++ put_filp(file); > + return ERR_PTR(error); > + } > + > - error = open_check_o_direct(file); > - if (error) { > - fput(file); > - file = ERR_PTR(error); > - } > - > + return file; > } > +EXPORT_SYMBOL(path_open); First of all, I'm still not at all convinced that this "noaccount" thing is sane, especially since path_open() is exported. But that aside, __get_empty_filp() needs to be shot, just for the name and calling conventions alone. It gets a bullshit argument (bool account) *AND* does not get the argument it does need. Note that the first thing get_empty_filp() (now __get...) does is const struct cred *cred = current_cred(); followed by f->f_cred = get_cred(cred); Now look at path_open(). What happens to the cred argument it gets? It goes to do_dentry_open(), where it gets passed to security_file_open() and not used by anything else. In security_file_open() we have it passed to ret = call_int_hook(file_open, 0, file, cred); and there are three instances of ->file_open() - apparmor, selinux and tomoyo. The last one ignores cred entirely; the other two do checks based on it, but *all* of them leave file->f_cred as it was. This is not a new crap. It had been inherited from dentry_open(), which got it from "CRED: Pass credentials through dentry_open()" back in 2008. Note that * among the callers of dentry_open() (20) and vfs_open() (2 more) only these fs/cachefiles/rdwr.c:913: file = dentry_open(&path, O_RDWR | O_LARGEFILE, cache->cache_cred); security/apparmor/file.c:695: devnull = dentry_open(&aa_null, O_RDWR, cred); security/selinux/hooks.c:2628: devnull = dentry_open(&selinux_null, O_RDWR, cred); get cred != current_cred(). Which helps masking the issue, but makes the decision to add that argument (instead of a separate helper) rather dubious. * overlayfs itself appears to *have* run into the problem, judging by old_cred = ovl_override_creds(inode->i_sb); realfile = path_open(&file->f_path, file->f_flags | O_NOATIME, realinode, current_cred(), false); revert_creds(old_cred); in there. Folks, if you have to go to that kind of contortions, why not do it right? * add static __alloc_file(cred), which would get cred pointer (and not use current_cred() internally), allocated a file (without bothering with nr_files) and returned it * have alloc_empty_file(cred) that would do the song and dance with nr_files (and used __alloc_file() internally). * use that as a replacement for get_empty_filp() - path_openat() would *probably* use current_cred() for argument, alloc_file() definitely would and dentry_open() would pass its cred argument. * in internal.h, static inline alloc_empty_file_noaccount(cred) would use __alloc_file() and set FMODE_NOACCOUNT in case of success. * do_dentry_open() loses the fucking cred argument - it should be in file->f_cred. * vfs_open() goes away - in your branch it's absolutely pointless. * path_open() loses its 'account' argument - it's always false. Uses alloc_empty_file_noaccount() to allocate the sucker. And for fsck sake, pass it the creds you want to use rather than playing that kind of games with override/revert.