2019-05-19 12:08:55 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* linux/fs/open.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 1991, 1992 Linus Torvalds
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/string.h>
|
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <linux/file.h>
|
2008-04-24 11:44:08 +00:00
|
|
|
#include <linux/fdtable.h>
|
[PATCH] inotify
inotify is intended to correct the deficiencies of dnotify, particularly
its inability to scale and its terrible user interface:
* dnotify requires the opening of one fd per each directory
that you intend to watch. This quickly results in too many
open files and pins removable media, preventing unmount.
* dnotify is directory-based. You only learn about changes to
directories. Sure, a change to a file in a directory affects
the directory, but you are then forced to keep a cache of
stat structures.
* dnotify's interface to user-space is awful. Signals?
inotify provides a more usable, simple, powerful solution to file change
notification:
* inotify's interface is a system call that returns a fd, not SIGIO.
You get a single fd, which is select()-able.
* inotify has an event that says "the filesystem that the item
you were watching is on was unmounted."
* inotify can watch directories or files.
Inotify is currently used by Beagle (a desktop search infrastructure),
Gamin (a FAM replacement), and other projects.
See Documentation/filesystems/inotify.txt.
Signed-off-by: Robert Love <rml@novell.com>
Cc: John McCutchan <ttb@tentacle.dhs.org>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-07-12 21:06:03 +00:00
|
|
|
#include <linux/fsnotify.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/tty.h>
|
|
|
|
#include <linux/namei.h>
|
|
|
|
#include <linux/backing-dev.h>
|
2006-01-11 20:17:46 +00:00
|
|
|
#include <linux/capability.h>
|
2008-07-04 16:59:58 +00:00
|
|
|
#include <linux/securebits.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/security.h>
|
|
|
|
#include <linux/mount.h>
|
2006-01-19 01:43:53 +00:00
|
|
|
#include <linux/fcntl.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 08:04:11 +00:00
|
|
|
#include <linux/slab.h>
|
2016-12-24 19:46:01 +00:00
|
|
|
#include <linux/uaccess.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/fs.h>
|
2005-06-23 07:09:58 +00:00
|
|
|
#include <linux/personality.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
#include <linux/pagemap.h>
|
|
|
|
#include <linux/syscalls.h>
|
2005-09-09 20:04:13 +00:00
|
|
|
#include <linux/rcupdate.h>
|
2005-11-03 16:00:25 +00:00
|
|
|
#include <linux/audit.h>
|
sys_fallocate() implementation on i386, x86_64 and powerpc
fallocate() is a new system call being proposed here which will allow
applications to preallocate space to any file(s) in a file system.
Each file system implementation that wants to use this feature will need
to support an inode operation called ->fallocate().
Applications can use this feature to avoid fragmentation to certain
level and thus get faster access speed. With preallocation, applications
also get a guarantee of space for particular file(s) - even if later the
the system becomes full.
Currently, glibc provides an interface called posix_fallocate() which
can be used for similar cause. Though this has the advantage of working
on all file systems, but it is quite slow (since it writes zeroes to
each block that has to be preallocated). Without a doubt, file systems
can do this more efficiently within the kernel, by implementing
the proposed fallocate() system call. It is expected that
posix_fallocate() will be modified to call this new system call first
and incase the kernel/filesystem does not implement it, it should fall
back to the current implementation of writing zeroes to the new blocks.
ToDos:
1. Implementation on other architectures (other than i386, x86_64,
and ppc). Patches for s390(x) and ia64 are already available from
previous posts, but it was decided that they should be added later
once fallocate is in the mainline. Hence not including those patches
in this take.
2. Changes to glibc,
a) to support fallocate() system call
b) to make posix_fallocate() and posix_fallocate64() call fallocate()
Signed-off-by: Amit Arora <aarora@in.ibm.com>
2007-07-18 01:42:44 +00:00
|
|
|
#include <linux/falloc.h>
|
2009-03-29 23:50:06 +00:00
|
|
|
#include <linux/fs_struct.h>
|
2009-12-16 11:27:40 +00:00
|
|
|
#include <linux/ima.h>
|
2009-12-18 01:30:52 +00:00
|
|
|
#include <linux/dnotify.h>
|
2013-02-24 18:49:08 +00:00
|
|
|
#include <linux/compat.h>
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-12-04 20:47:36 +00:00
|
|
|
#include "internal.h"
|
|
|
|
|
2006-01-08 09:02:39 +00:00
|
|
|
int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
|
|
|
|
struct file *filp)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2009-08-21 02:29:03 +00:00
|
|
|
int ret;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct iattr newattrs;
|
|
|
|
|
|
|
|
/* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
|
|
|
|
if (length < 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
newattrs.ia_size = length;
|
2006-01-08 09:02:39 +00:00
|
|
|
newattrs.ia_valid = ATTR_SIZE | time_attrs;
|
2005-11-07 08:59:49 +00:00
|
|
|
if (filp) {
|
|
|
|
newattrs.ia_file = filp;
|
|
|
|
newattrs.ia_valid |= ATTR_FILE;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2015-05-21 14:05:55 +00:00
|
|
|
/* Remove suid, sgid, and file capabilities on truncate too */
|
|
|
|
ret = dentry_needs_remove_privs(dentry);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
2009-08-21 02:29:03 +00:00
|
|
|
if (ret)
|
|
|
|
newattrs.ia_valid |= ret | ATTR_FORCE;
|
2007-05-09 03:10:00 +00:00
|
|
|
|
2016-01-22 20:40:57 +00:00
|
|
|
inode_lock(dentry->d_inode);
|
2011-09-20 21:19:26 +00:00
|
|
|
/* Note any delegations or leases have already been broken: */
|
|
|
|
ret = notify_change(dentry, &newattrs, NULL);
|
2016-01-22 20:40:57 +00:00
|
|
|
inode_unlock(dentry->d_inode);
|
2009-08-21 02:29:03 +00:00
|
|
|
return ret;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2016-03-25 18:24:09 +00:00
|
|
|
long vfs_truncate(const struct path *path, loff_t length)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2008-07-22 13:59:21 +00:00
|
|
|
struct inode *inode;
|
2012-12-20 21:52:36 +00:00
|
|
|
long error;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-12-20 21:52:36 +00:00
|
|
|
inode = path->dentry->d_inode;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
/* For directories it's -EISDIR, for other non-regulars - -EINVAL */
|
|
|
|
if (S_ISDIR(inode->i_mode))
|
2012-12-20 21:52:36 +00:00
|
|
|
return -EISDIR;
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!S_ISREG(inode->i_mode))
|
2012-12-20 21:52:36 +00:00
|
|
|
return -EINVAL;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-12-20 21:52:36 +00:00
|
|
|
error = mnt_want_write(path->mnt);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (error)
|
2012-12-20 21:52:36 +00:00
|
|
|
goto out;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-07-22 12:09:30 +00:00
|
|
|
error = inode_permission(inode, MAY_WRITE);
|
2008-02-15 22:37:52 +00:00
|
|
|
if (error)
|
|
|
|
goto mnt_drop_write_and_out;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
error = -EPERM;
|
2008-06-24 14:50:12 +00:00
|
|
|
if (IS_APPEND(inode))
|
2008-02-15 22:37:52 +00:00
|
|
|
goto mnt_drop_write_and_out;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2018-07-18 13:44:43 +00:00
|
|
|
error = get_write_access(inode);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (error)
|
2008-02-15 22:37:52 +00:00
|
|
|
goto mnt_drop_write_and_out;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2007-07-31 07:39:12 +00:00
|
|
|
/*
|
|
|
|
* Make sure that there are no leases. get_write_access() protects
|
|
|
|
* against the truncate racing with a lease-granting setlease().
|
|
|
|
*/
|
2009-12-24 11:47:55 +00:00
|
|
|
error = break_lease(inode, O_WRONLY);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (error)
|
2007-07-31 07:39:12 +00:00
|
|
|
goto put_write_and_out;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
error = locks_verify_truncate(inode, NULL, length);
|
2008-12-17 04:24:15 +00:00
|
|
|
if (!error)
|
2012-12-20 21:52:36 +00:00
|
|
|
error = security_path_truncate(path);
|
2010-03-03 14:05:06 +00:00
|
|
|
if (!error)
|
2012-12-20 21:52:36 +00:00
|
|
|
error = do_truncate(path->dentry, length, 0, NULL);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2007-07-31 07:39:12 +00:00
|
|
|
put_write_and_out:
|
2018-07-18 13:44:43 +00:00
|
|
|
put_write_access(inode);
|
2008-02-15 22:37:52 +00:00
|
|
|
mnt_drop_write_and_out:
|
2012-12-20 21:52:36 +00:00
|
|
|
mnt_drop_write(path->mnt);
|
2005-04-16 22:20:36 +00:00
|
|
|
out:
|
|
|
|
return error;
|
|
|
|
}
|
2012-12-20 21:52:36 +00:00
|
|
|
EXPORT_SYMBOL_GPL(vfs_truncate);
|
|
|
|
|
2018-03-19 16:32:11 +00:00
|
|
|
long do_sys_truncate(const char __user *pathname, loff_t length)
|
2012-12-20 21:52:36 +00:00
|
|
|
{
|
2012-12-11 17:10:11 +00:00
|
|
|
unsigned int lookup_flags = LOOKUP_FOLLOW;
|
2012-12-20 21:52:36 +00:00
|
|
|
struct path path;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (length < 0) /* sorry, but loff_t says... */
|
|
|
|
return -EINVAL;
|
|
|
|
|
2012-12-11 17:10:11 +00:00
|
|
|
retry:
|
|
|
|
error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
|
2012-12-20 21:52:36 +00:00
|
|
|
if (!error) {
|
|
|
|
error = vfs_truncate(&path, length);
|
|
|
|
path_put(&path);
|
|
|
|
}
|
2012-12-11 17:10:11 +00:00
|
|
|
if (retry_estale(error, lookup_flags)) {
|
|
|
|
lookup_flags |= LOOKUP_REVAL;
|
|
|
|
goto retry;
|
|
|
|
}
|
2012-12-20 21:52:36 +00:00
|
|
|
return error;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-09-23 15:49:55 +00:00
|
|
|
SYSCALL_DEFINE2(truncate, const char __user *, path, long, length)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2009-09-23 15:49:55 +00:00
|
|
|
return do_sys_truncate(path, length);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2013-02-24 18:49:08 +00:00
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
COMPAT_SYSCALL_DEFINE2(truncate, const char __user *, path, compat_off_t, length)
|
|
|
|
{
|
|
|
|
return do_sys_truncate(path, length);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-03-11 10:34:54 +00:00
|
|
|
long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-08-27 00:13:36 +00:00
|
|
|
struct inode *inode;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct dentry *dentry;
|
2012-08-28 16:52:22 +00:00
|
|
|
struct fd f;
|
2005-04-16 22:20:36 +00:00
|
|
|
int error;
|
|
|
|
|
|
|
|
error = -EINVAL;
|
|
|
|
if (length < 0)
|
|
|
|
goto out;
|
|
|
|
error = -EBADF;
|
2012-08-28 16:52:22 +00:00
|
|
|
f = fdget(fd);
|
|
|
|
if (!f.file)
|
2005-04-16 22:20:36 +00:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* explicitly opened as large or we are on 64-bit box */
|
2012-08-28 16:52:22 +00:00
|
|
|
if (f.file->f_flags & O_LARGEFILE)
|
2005-04-16 22:20:36 +00:00
|
|
|
small = 0;
|
|
|
|
|
2012-08-28 16:52:22 +00:00
|
|
|
dentry = f.file->f_path.dentry;
|
2005-04-16 22:20:36 +00:00
|
|
|
inode = dentry->d_inode;
|
|
|
|
error = -EINVAL;
|
2012-08-28 16:52:22 +00:00
|
|
|
if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE))
|
2005-04-16 22:20:36 +00:00
|
|
|
goto out_putf;
|
|
|
|
|
|
|
|
error = -EINVAL;
|
|
|
|
/* Cannot ftruncate over 2^31 bytes without large file support */
|
|
|
|
if (small && length > MAX_NON_LFS)
|
|
|
|
goto out_putf;
|
|
|
|
|
|
|
|
error = -EPERM;
|
2017-04-08 11:49:06 +00:00
|
|
|
/* Check IS_APPEND on real upper inode */
|
|
|
|
if (IS_APPEND(file_inode(f.file)))
|
2005-04-16 22:20:36 +00:00
|
|
|
goto out_putf;
|
|
|
|
|
2012-06-12 14:20:37 +00:00
|
|
|
sb_start_write(inode->i_sb);
|
2012-08-28 16:52:22 +00:00
|
|
|
error = locks_verify_truncate(inode, f.file, length);
|
2008-12-17 04:24:15 +00:00
|
|
|
if (!error)
|
2012-08-28 16:52:22 +00:00
|
|
|
error = security_path_truncate(&f.file->f_path);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!error)
|
2012-08-28 16:52:22 +00:00
|
|
|
error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, f.file);
|
2012-06-12 14:20:37 +00:00
|
|
|
sb_end_write(inode->i_sb);
|
2005-04-16 22:20:36 +00:00
|
|
|
out_putf:
|
2012-08-28 16:52:22 +00:00
|
|
|
fdput(f);
|
2005-04-16 22:20:36 +00:00
|
|
|
out:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2009-01-14 13:14:12 +00:00
|
|
|
SYSCALL_DEFINE2(ftruncate, unsigned int, fd, unsigned long, length)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2013-01-21 20:25:54 +00:00
|
|
|
return do_sys_ftruncate(fd, length, 1);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2013-02-24 18:49:08 +00:00
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
COMPAT_SYSCALL_DEFINE2(ftruncate, unsigned int, fd, compat_ulong_t, length)
|
|
|
|
{
|
|
|
|
return do_sys_ftruncate(fd, length, 1);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/* LFS versions of truncate are only needed on 32 bit machines */
|
|
|
|
#if BITS_PER_LONG == 32
|
2013-01-21 20:16:58 +00:00
|
|
|
SYSCALL_DEFINE2(truncate64, const char __user *, path, loff_t, length)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
return do_sys_truncate(path, length);
|
|
|
|
}
|
|
|
|
|
2013-01-21 20:16:58 +00:00
|
|
|
SYSCALL_DEFINE2(ftruncate64, unsigned int, fd, loff_t, length)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2013-01-21 20:25:54 +00:00
|
|
|
return do_sys_ftruncate(fd, length, 0);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
2009-01-14 13:14:02 +00:00
|
|
|
#endif /* BITS_PER_LONG == 32 */
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-06-19 18:28:07 +00:00
|
|
|
|
2014-11-07 19:44:25 +00:00
|
|
|
int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
|
sys_fallocate() implementation on i386, x86_64 and powerpc
fallocate() is a new system call being proposed here which will allow
applications to preallocate space to any file(s) in a file system.
Each file system implementation that wants to use this feature will need
to support an inode operation called ->fallocate().
Applications can use this feature to avoid fragmentation to certain
level and thus get faster access speed. With preallocation, applications
also get a guarantee of space for particular file(s) - even if later the
the system becomes full.
Currently, glibc provides an interface called posix_fallocate() which
can be used for similar cause. Though this has the advantage of working
on all file systems, but it is quite slow (since it writes zeroes to
each block that has to be preallocated). Without a doubt, file systems
can do this more efficiently within the kernel, by implementing
the proposed fallocate() system call. It is expected that
posix_fallocate() will be modified to call this new system call first
and incase the kernel/filesystem does not implement it, it should fall
back to the current implementation of writing zeroes to the new blocks.
ToDos:
1. Implementation on other architectures (other than i386, x86_64,
and ppc). Patches for s390(x) and ia64 are already available from
previous posts, but it was decided that they should be added later
once fallocate is in the mainline. Hence not including those patches
in this take.
2. Changes to glibc,
a) to support fallocate() system call
b) to make posix_fallocate() and posix_fallocate64() call fallocate()
Signed-off-by: Amit Arora <aarora@in.ibm.com>
2007-07-18 01:42:44 +00:00
|
|
|
{
|
2013-01-23 22:07:38 +00:00
|
|
|
struct inode *inode = file_inode(file);
|
2009-06-19 18:28:07 +00:00
|
|
|
long ret;
|
sys_fallocate() implementation on i386, x86_64 and powerpc
fallocate() is a new system call being proposed here which will allow
applications to preallocate space to any file(s) in a file system.
Each file system implementation that wants to use this feature will need
to support an inode operation called ->fallocate().
Applications can use this feature to avoid fragmentation to certain
level and thus get faster access speed. With preallocation, applications
also get a guarantee of space for particular file(s) - even if later the
the system becomes full.
Currently, glibc provides an interface called posix_fallocate() which
can be used for similar cause. Though this has the advantage of working
on all file systems, but it is quite slow (since it writes zeroes to
each block that has to be preallocated). Without a doubt, file systems
can do this more efficiently within the kernel, by implementing
the proposed fallocate() system call. It is expected that
posix_fallocate() will be modified to call this new system call first
and incase the kernel/filesystem does not implement it, it should fall
back to the current implementation of writing zeroes to the new blocks.
ToDos:
1. Implementation on other architectures (other than i386, x86_64,
and ppc). Patches for s390(x) and ia64 are already available from
previous posts, but it was decided that they should be added later
once fallocate is in the mainline. Hence not including those patches
in this take.
2. Changes to glibc,
a) to support fallocate() system call
b) to make posix_fallocate() and posix_fallocate64() call fallocate()
Signed-off-by: Amit Arora <aarora@in.ibm.com>
2007-07-18 01:42:44 +00:00
|
|
|
|
|
|
|
if (offset < 0 || len <= 0)
|
2009-06-19 18:28:07 +00:00
|
|
|
return -EINVAL;
|
sys_fallocate() implementation on i386, x86_64 and powerpc
fallocate() is a new system call being proposed here which will allow
applications to preallocate space to any file(s) in a file system.
Each file system implementation that wants to use this feature will need
to support an inode operation called ->fallocate().
Applications can use this feature to avoid fragmentation to certain
level and thus get faster access speed. With preallocation, applications
also get a guarantee of space for particular file(s) - even if later the
the system becomes full.
Currently, glibc provides an interface called posix_fallocate() which
can be used for similar cause. Though this has the advantage of working
on all file systems, but it is quite slow (since it writes zeroes to
each block that has to be preallocated). Without a doubt, file systems
can do this more efficiently within the kernel, by implementing
the proposed fallocate() system call. It is expected that
posix_fallocate() will be modified to call this new system call first
and incase the kernel/filesystem does not implement it, it should fall
back to the current implementation of writing zeroes to the new blocks.
ToDos:
1. Implementation on other architectures (other than i386, x86_64,
and ppc). Patches for s390(x) and ia64 are already available from
previous posts, but it was decided that they should be added later
once fallocate is in the mainline. Hence not including those patches
in this take.
2. Changes to glibc,
a) to support fallocate() system call
b) to make posix_fallocate() and posix_fallocate64() call fallocate()
Signed-off-by: Amit Arora <aarora@in.ibm.com>
2007-07-18 01:42:44 +00:00
|
|
|
|
|
|
|
/* Return error if mode is not supported */
|
2015-03-25 04:07:05 +00:00
|
|
|
if (mode & ~FALLOC_FL_SUPPORTED_MASK)
|
2014-03-13 08:07:42 +00:00
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
/* Punch hole and zero range are mutually exclusive */
|
|
|
|
if ((mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) ==
|
|
|
|
(FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE))
|
2010-11-18 01:46:15 +00:00
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
/* Punch hole must have keep size set */
|
|
|
|
if ((mode & FALLOC_FL_PUNCH_HOLE) &&
|
|
|
|
!(mode & FALLOC_FL_KEEP_SIZE))
|
2009-06-19 18:28:07 +00:00
|
|
|
return -EOPNOTSUPP;
|
sys_fallocate() implementation on i386, x86_64 and powerpc
fallocate() is a new system call being proposed here which will allow
applications to preallocate space to any file(s) in a file system.
Each file system implementation that wants to use this feature will need
to support an inode operation called ->fallocate().
Applications can use this feature to avoid fragmentation to certain
level and thus get faster access speed. With preallocation, applications
also get a guarantee of space for particular file(s) - even if later the
the system becomes full.
Currently, glibc provides an interface called posix_fallocate() which
can be used for similar cause. Though this has the advantage of working
on all file systems, but it is quite slow (since it writes zeroes to
each block that has to be preallocated). Without a doubt, file systems
can do this more efficiently within the kernel, by implementing
the proposed fallocate() system call. It is expected that
posix_fallocate() will be modified to call this new system call first
and incase the kernel/filesystem does not implement it, it should fall
back to the current implementation of writing zeroes to the new blocks.
ToDos:
1. Implementation on other architectures (other than i386, x86_64,
and ppc). Patches for s390(x) and ia64 are already available from
previous posts, but it was decided that they should be added later
once fallocate is in the mainline. Hence not including those patches
in this take.
2. Changes to glibc,
a) to support fallocate() system call
b) to make posix_fallocate() and posix_fallocate64() call fallocate()
Signed-off-by: Amit Arora <aarora@in.ibm.com>
2007-07-18 01:42:44 +00:00
|
|
|
|
2014-02-23 23:58:15 +00:00
|
|
|
/* Collapse range should only be used exclusively. */
|
|
|
|
if ((mode & FALLOC_FL_COLLAPSE_RANGE) &&
|
|
|
|
(mode & ~FALLOC_FL_COLLAPSE_RANGE))
|
|
|
|
return -EINVAL;
|
|
|
|
|
2015-03-25 04:07:05 +00:00
|
|
|
/* Insert range should only be used exclusively. */
|
|
|
|
if ((mode & FALLOC_FL_INSERT_RANGE) &&
|
|
|
|
(mode & ~FALLOC_FL_INSERT_RANGE))
|
|
|
|
return -EINVAL;
|
|
|
|
|
2016-10-03 16:11:14 +00:00
|
|
|
/* Unshare range should only be used with allocate mode. */
|
|
|
|
if ((mode & FALLOC_FL_UNSHARE_RANGE) &&
|
|
|
|
(mode & ~(FALLOC_FL_UNSHARE_RANGE | FALLOC_FL_KEEP_SIZE)))
|
|
|
|
return -EINVAL;
|
|
|
|
|
sys_fallocate() implementation on i386, x86_64 and powerpc
fallocate() is a new system call being proposed here which will allow
applications to preallocate space to any file(s) in a file system.
Each file system implementation that wants to use this feature will need
to support an inode operation called ->fallocate().
Applications can use this feature to avoid fragmentation to certain
level and thus get faster access speed. With preallocation, applications
also get a guarantee of space for particular file(s) - even if later the
the system becomes full.
Currently, glibc provides an interface called posix_fallocate() which
can be used for similar cause. Though this has the advantage of working
on all file systems, but it is quite slow (since it writes zeroes to
each block that has to be preallocated). Without a doubt, file systems
can do this more efficiently within the kernel, by implementing
the proposed fallocate() system call. It is expected that
posix_fallocate() will be modified to call this new system call first
and incase the kernel/filesystem does not implement it, it should fall
back to the current implementation of writing zeroes to the new blocks.
ToDos:
1. Implementation on other architectures (other than i386, x86_64,
and ppc). Patches for s390(x) and ia64 are already available from
previous posts, but it was decided that they should be added later
once fallocate is in the mainline. Hence not including those patches
in this take.
2. Changes to glibc,
a) to support fallocate() system call
b) to make posix_fallocate() and posix_fallocate64() call fallocate()
Signed-off-by: Amit Arora <aarora@in.ibm.com>
2007-07-18 01:42:44 +00:00
|
|
|
if (!(file->f_mode & FMODE_WRITE))
|
2009-06-19 18:28:07 +00:00
|
|
|
return -EBADF;
|
2011-03-05 10:10:19 +00:00
|
|
|
|
2014-02-23 23:58:15 +00:00
|
|
|
/*
|
2014-04-12 13:51:34 +00:00
|
|
|
* We can only allow pure fallocate on append only files
|
2014-02-23 23:58:15 +00:00
|
|
|
*/
|
2014-04-12 13:51:34 +00:00
|
|
|
if ((mode & ~FALLOC_FL_KEEP_SIZE) && IS_APPEND(inode))
|
2011-03-05 10:10:19 +00:00
|
|
|
return -EPERM;
|
|
|
|
|
|
|
|
if (IS_IMMUTABLE(inode))
|
|
|
|
return -EPERM;
|
|
|
|
|
2014-04-12 14:05:37 +00:00
|
|
|
/*
|
2014-06-25 04:45:08 +00:00
|
|
|
* We cannot allow any fallocate operation on an active swapfile
|
2014-04-12 14:05:37 +00:00
|
|
|
*/
|
|
|
|
if (IS_SWAPFILE(inode))
|
2014-06-25 04:45:08 +00:00
|
|
|
return -ETXTBSY;
|
2014-04-12 14:05:37 +00:00
|
|
|
|
sys_fallocate() implementation on i386, x86_64 and powerpc
fallocate() is a new system call being proposed here which will allow
applications to preallocate space to any file(s) in a file system.
Each file system implementation that wants to use this feature will need
to support an inode operation called ->fallocate().
Applications can use this feature to avoid fragmentation to certain
level and thus get faster access speed. With preallocation, applications
also get a guarantee of space for particular file(s) - even if later the
the system becomes full.
Currently, glibc provides an interface called posix_fallocate() which
can be used for similar cause. Though this has the advantage of working
on all file systems, but it is quite slow (since it writes zeroes to
each block that has to be preallocated). Without a doubt, file systems
can do this more efficiently within the kernel, by implementing
the proposed fallocate() system call. It is expected that
posix_fallocate() will be modified to call this new system call first
and incase the kernel/filesystem does not implement it, it should fall
back to the current implementation of writing zeroes to the new blocks.
ToDos:
1. Implementation on other architectures (other than i386, x86_64,
and ppc). Patches for s390(x) and ia64 are already available from
previous posts, but it was decided that they should be added later
once fallocate is in the mainline. Hence not including those patches
in this take.
2. Changes to glibc,
a) to support fallocate() system call
b) to make posix_fallocate() and posix_fallocate64() call fallocate()
Signed-off-by: Amit Arora <aarora@in.ibm.com>
2007-07-18 01:42:44 +00:00
|
|
|
/*
|
|
|
|
* Revalidate the write permissions, in case security policy has
|
|
|
|
* changed since the files were opened.
|
|
|
|
*/
|
|
|
|
ret = security_file_permission(file, MAY_WRITE);
|
|
|
|
if (ret)
|
2009-06-19 18:28:07 +00:00
|
|
|
return ret;
|
sys_fallocate() implementation on i386, x86_64 and powerpc
fallocate() is a new system call being proposed here which will allow
applications to preallocate space to any file(s) in a file system.
Each file system implementation that wants to use this feature will need
to support an inode operation called ->fallocate().
Applications can use this feature to avoid fragmentation to certain
level and thus get faster access speed. With preallocation, applications
also get a guarantee of space for particular file(s) - even if later the
the system becomes full.
Currently, glibc provides an interface called posix_fallocate() which
can be used for similar cause. Though this has the advantage of working
on all file systems, but it is quite slow (since it writes zeroes to
each block that has to be preallocated). Without a doubt, file systems
can do this more efficiently within the kernel, by implementing
the proposed fallocate() system call. It is expected that
posix_fallocate() will be modified to call this new system call first
and incase the kernel/filesystem does not implement it, it should fall
back to the current implementation of writing zeroes to the new blocks.
ToDos:
1. Implementation on other architectures (other than i386, x86_64,
and ppc). Patches for s390(x) and ia64 are already available from
previous posts, but it was decided that they should be added later
once fallocate is in the mainline. Hence not including those patches
in this take.
2. Changes to glibc,
a) to support fallocate() system call
b) to make posix_fallocate() and posix_fallocate64() call fallocate()
Signed-off-by: Amit Arora <aarora@in.ibm.com>
2007-07-18 01:42:44 +00:00
|
|
|
|
|
|
|
if (S_ISFIFO(inode->i_mode))
|
2009-06-19 18:28:07 +00:00
|
|
|
return -ESPIPE;
|
sys_fallocate() implementation on i386, x86_64 and powerpc
fallocate() is a new system call being proposed here which will allow
applications to preallocate space to any file(s) in a file system.
Each file system implementation that wants to use this feature will need
to support an inode operation called ->fallocate().
Applications can use this feature to avoid fragmentation to certain
level and thus get faster access speed. With preallocation, applications
also get a guarantee of space for particular file(s) - even if later the
the system becomes full.
Currently, glibc provides an interface called posix_fallocate() which
can be used for similar cause. Though this has the advantage of working
on all file systems, but it is quite slow (since it writes zeroes to
each block that has to be preallocated). Without a doubt, file systems
can do this more efficiently within the kernel, by implementing
the proposed fallocate() system call. It is expected that
posix_fallocate() will be modified to call this new system call first
and incase the kernel/filesystem does not implement it, it should fall
back to the current implementation of writing zeroes to the new blocks.
ToDos:
1. Implementation on other architectures (other than i386, x86_64,
and ppc). Patches for s390(x) and ia64 are already available from
previous posts, but it was decided that they should be added later
once fallocate is in the mainline. Hence not including those patches
in this take.
2. Changes to glibc,
a) to support fallocate() system call
b) to make posix_fallocate() and posix_fallocate64() call fallocate()
Signed-off-by: Amit Arora <aarora@in.ibm.com>
2007-07-18 01:42:44 +00:00
|
|
|
|
2017-01-31 08:34:55 +00:00
|
|
|
if (S_ISDIR(inode->i_mode))
|
|
|
|
return -EISDIR;
|
|
|
|
|
|
|
|
if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
|
2009-06-19 18:28:07 +00:00
|
|
|
return -ENODEV;
|
sys_fallocate() implementation on i386, x86_64 and powerpc
fallocate() is a new system call being proposed here which will allow
applications to preallocate space to any file(s) in a file system.
Each file system implementation that wants to use this feature will need
to support an inode operation called ->fallocate().
Applications can use this feature to avoid fragmentation to certain
level and thus get faster access speed. With preallocation, applications
also get a guarantee of space for particular file(s) - even if later the
the system becomes full.
Currently, glibc provides an interface called posix_fallocate() which
can be used for similar cause. Though this has the advantage of working
on all file systems, but it is quite slow (since it writes zeroes to
each block that has to be preallocated). Without a doubt, file systems
can do this more efficiently within the kernel, by implementing
the proposed fallocate() system call. It is expected that
posix_fallocate() will be modified to call this new system call first
and incase the kernel/filesystem does not implement it, it should fall
back to the current implementation of writing zeroes to the new blocks.
ToDos:
1. Implementation on other architectures (other than i386, x86_64,
and ppc). Patches for s390(x) and ia64 are already available from
previous posts, but it was decided that they should be added later
once fallocate is in the mainline. Hence not including those patches
in this take.
2. Changes to glibc,
a) to support fallocate() system call
b) to make posix_fallocate() and posix_fallocate64() call fallocate()
Signed-off-by: Amit Arora <aarora@in.ibm.com>
2007-07-18 01:42:44 +00:00
|
|
|
|
|
|
|
/* Check for wrap through zero too */
|
|
|
|
if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
|
2009-06-19 18:28:07 +00:00
|
|
|
return -EFBIG;
|
sys_fallocate() implementation on i386, x86_64 and powerpc
fallocate() is a new system call being proposed here which will allow
applications to preallocate space to any file(s) in a file system.
Each file system implementation that wants to use this feature will need
to support an inode operation called ->fallocate().
Applications can use this feature to avoid fragmentation to certain
level and thus get faster access speed. With preallocation, applications
also get a guarantee of space for particular file(s) - even if later the
the system becomes full.
Currently, glibc provides an interface called posix_fallocate() which
can be used for similar cause. Though this has the advantage of working
on all file systems, but it is quite slow (since it writes zeroes to
each block that has to be preallocated). Without a doubt, file systems
can do this more efficiently within the kernel, by implementing
the proposed fallocate() system call. It is expected that
posix_fallocate() will be modified to call this new system call first
and incase the kernel/filesystem does not implement it, it should fall
back to the current implementation of writing zeroes to the new blocks.
ToDos:
1. Implementation on other architectures (other than i386, x86_64,
and ppc). Patches for s390(x) and ia64 are already available from
previous posts, but it was decided that they should be added later
once fallocate is in the mainline. Hence not including those patches
in this take.
2. Changes to glibc,
a) to support fallocate() system call
b) to make posix_fallocate() and posix_fallocate64() call fallocate()
Signed-off-by: Amit Arora <aarora@in.ibm.com>
2007-07-18 01:42:44 +00:00
|
|
|
|
2011-01-14 12:07:43 +00:00
|
|
|
if (!file->f_op->fallocate)
|
2009-06-19 18:28:07 +00:00
|
|
|
return -EOPNOTSUPP;
|
sys_fallocate() implementation on i386, x86_64 and powerpc
fallocate() is a new system call being proposed here which will allow
applications to preallocate space to any file(s) in a file system.
Each file system implementation that wants to use this feature will need
to support an inode operation called ->fallocate().
Applications can use this feature to avoid fragmentation to certain
level and thus get faster access speed. With preallocation, applications
also get a guarantee of space for particular file(s) - even if later the
the system becomes full.
Currently, glibc provides an interface called posix_fallocate() which
can be used for similar cause. Though this has the advantage of working
on all file systems, but it is quite slow (since it writes zeroes to
each block that has to be preallocated). Without a doubt, file systems
can do this more efficiently within the kernel, by implementing
the proposed fallocate() system call. It is expected that
posix_fallocate() will be modified to call this new system call first
and incase the kernel/filesystem does not implement it, it should fall
back to the current implementation of writing zeroes to the new blocks.
ToDos:
1. Implementation on other architectures (other than i386, x86_64,
and ppc). Patches for s390(x) and ia64 are already available from
previous posts, but it was decided that they should be added later
once fallocate is in the mainline. Hence not including those patches
in this take.
2. Changes to glibc,
a) to support fallocate() system call
b) to make posix_fallocate() and posix_fallocate64() call fallocate()
Signed-off-by: Amit Arora <aarora@in.ibm.com>
2007-07-18 01:42:44 +00:00
|
|
|
|
2017-01-31 08:34:57 +00:00
|
|
|
file_start_write(file);
|
2012-06-12 14:20:37 +00:00
|
|
|
ret = file->f_op->fallocate(file, mode, offset, len);
|
2014-12-13 00:58:34 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Create inotify and fanotify events.
|
|
|
|
*
|
|
|
|
* To keep the logic simple always create events if fallocate succeeds.
|
|
|
|
* This implies that events are even created if the file size remains
|
|
|
|
* unchanged, e.g. when using flag FALLOC_FL_KEEP_SIZE.
|
|
|
|
*/
|
|
|
|
if (ret == 0)
|
|
|
|
fsnotify_modify(file);
|
|
|
|
|
2017-01-31 08:34:57 +00:00
|
|
|
file_end_write(file);
|
2012-06-12 14:20:37 +00:00
|
|
|
return ret;
|
2009-06-19 18:28:07 +00:00
|
|
|
}
|
2014-11-07 19:44:25 +00:00
|
|
|
EXPORT_SYMBOL_GPL(vfs_fallocate);
|
2009-06-19 18:28:07 +00:00
|
|
|
|
2018-03-19 16:46:32 +00:00
|
|
|
int ksys_fallocate(int fd, int mode, loff_t offset, loff_t len)
|
2009-06-19 18:28:07 +00:00
|
|
|
{
|
2012-08-28 16:52:22 +00:00
|
|
|
struct fd f = fdget(fd);
|
2009-06-19 18:28:07 +00:00
|
|
|
int error = -EBADF;
|
|
|
|
|
2012-08-28 16:52:22 +00:00
|
|
|
if (f.file) {
|
2014-11-07 19:44:25 +00:00
|
|
|
error = vfs_fallocate(f.file, mode, offset, len);
|
2012-08-28 16:52:22 +00:00
|
|
|
fdput(f);
|
2009-06-19 18:28:07 +00:00
|
|
|
}
|
|
|
|
return error;
|
sys_fallocate() implementation on i386, x86_64 and powerpc
fallocate() is a new system call being proposed here which will allow
applications to preallocate space to any file(s) in a file system.
Each file system implementation that wants to use this feature will need
to support an inode operation called ->fallocate().
Applications can use this feature to avoid fragmentation to certain
level and thus get faster access speed. With preallocation, applications
also get a guarantee of space for particular file(s) - even if later the
the system becomes full.
Currently, glibc provides an interface called posix_fallocate() which
can be used for similar cause. Though this has the advantage of working
on all file systems, but it is quite slow (since it writes zeroes to
each block that has to be preallocated). Without a doubt, file systems
can do this more efficiently within the kernel, by implementing
the proposed fallocate() system call. It is expected that
posix_fallocate() will be modified to call this new system call first
and incase the kernel/filesystem does not implement it, it should fall
back to the current implementation of writing zeroes to the new blocks.
ToDos:
1. Implementation on other architectures (other than i386, x86_64,
and ppc). Patches for s390(x) and ia64 are already available from
previous posts, but it was decided that they should be added later
once fallocate is in the mainline. Hence not including those patches
in this take.
2. Changes to glibc,
a) to support fallocate() system call
b) to make posix_fallocate() and posix_fallocate64() call fallocate()
Signed-off-by: Amit Arora <aarora@in.ibm.com>
2007-07-18 01:42:44 +00:00
|
|
|
}
|
2009-06-19 18:28:07 +00:00
|
|
|
|
2018-03-19 16:46:32 +00:00
|
|
|
SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
|
|
|
|
{
|
|
|
|
return ksys_fallocate(fd, mode, offset, len);
|
|
|
|
}
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
/*
|
|
|
|
* access() needs to use the real uid/gid, not the effective uid/gid.
|
|
|
|
* We do this by temporarily clearing all FS-related capabilities and
|
|
|
|
* switching the fsuid/fsgid around to the real ones.
|
|
|
|
*/
|
2018-03-11 10:34:54 +00:00
|
|
|
long do_faccessat(int dfd, const char __user *filename, int mode)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
CRED: Inaugurate COW credentials
Inaugurate copy-on-write credentials management. This uses RCU to manage the
credentials pointer in the task_struct with respect to accesses by other tasks.
A process may only modify its own credentials, and so does not need locking to
access or modify its own credentials.
A mutex (cred_replace_mutex) is added to the task_struct to control the effect
of PTRACE_ATTACHED on credential calculations, particularly with respect to
execve().
With this patch, the contents of an active credentials struct may not be
changed directly; rather a new set of credentials must be prepared, modified
and committed using something like the following sequence of events:
struct cred *new = prepare_creds();
int ret = blah(new);
if (ret < 0) {
abort_creds(new);
return ret;
}
return commit_creds(new);
There are some exceptions to this rule: the keyrings pointed to by the active
credentials may be instantiated - keyrings violate the COW rule as managing
COW keyrings is tricky, given that it is possible for a task to directly alter
the keys in a keyring in use by another task.
To help enforce this, various pointers to sets of credentials, such as those in
the task_struct, are declared const. The purpose of this is compile-time
discouragement of altering credentials through those pointers. Once a set of
credentials has been made public through one of these pointers, it may not be
modified, except under special circumstances:
(1) Its reference count may incremented and decremented.
(2) The keyrings to which it points may be modified, but not replaced.
The only safe way to modify anything else is to create a replacement and commit
using the functions described in Documentation/credentials.txt (which will be
added by a later patch).
This patch and the preceding patches have been tested with the LTP SELinux
testsuite.
This patch makes several logical sets of alteration:
(1) execve().
This now prepares and commits credentials in various places in the
security code rather than altering the current creds directly.
(2) Temporary credential overrides.
do_coredump() and sys_faccessat() now prepare their own credentials and
temporarily override the ones currently on the acting thread, whilst
preventing interference from other threads by holding cred_replace_mutex
on the thread being dumped.
This will be replaced in a future patch by something that hands down the
credentials directly to the functions being called, rather than altering
the task's objective credentials.
(3) LSM interface.
A number of functions have been changed, added or removed:
(*) security_capset_check(), ->capset_check()
(*) security_capset_set(), ->capset_set()
Removed in favour of security_capset().
(*) security_capset(), ->capset()
New. This is passed a pointer to the new creds, a pointer to the old
creds and the proposed capability sets. It should fill in the new
creds or return an error. All pointers, barring the pointer to the
new creds, are now const.
(*) security_bprm_apply_creds(), ->bprm_apply_creds()
Changed; now returns a value, which will cause the process to be
killed if it's an error.
(*) security_task_alloc(), ->task_alloc_security()
Removed in favour of security_prepare_creds().
(*) security_cred_free(), ->cred_free()
New. Free security data attached to cred->security.
(*) security_prepare_creds(), ->cred_prepare()
New. Duplicate any security data attached to cred->security.
(*) security_commit_creds(), ->cred_commit()
New. Apply any security effects for the upcoming installation of new
security by commit_creds().
(*) security_task_post_setuid(), ->task_post_setuid()
Removed in favour of security_task_fix_setuid().
(*) security_task_fix_setuid(), ->task_fix_setuid()
Fix up the proposed new credentials for setuid(). This is used by
cap_set_fix_setuid() to implicitly adjust capabilities in line with
setuid() changes. Changes are made to the new credentials, rather
than the task itself as in security_task_post_setuid().
(*) security_task_reparent_to_init(), ->task_reparent_to_init()
Removed. Instead the task being reparented to init is referred
directly to init's credentials.
NOTE! This results in the loss of some state: SELinux's osid no
longer records the sid of the thread that forked it.
(*) security_key_alloc(), ->key_alloc()
(*) security_key_permission(), ->key_permission()
Changed. These now take cred pointers rather than task pointers to
refer to the security context.
(4) sys_capset().
This has been simplified and uses less locking. The LSM functions it
calls have been merged.
(5) reparent_to_kthreadd().
This gives the current thread the same credentials as init by simply using
commit_thread() to point that way.
(6) __sigqueue_alloc() and switch_uid()
__sigqueue_alloc() can't stop the target task from changing its creds
beneath it, so this function gets a reference to the currently applicable
user_struct which it then passes into the sigqueue struct it returns if
successful.
switch_uid() is now called from commit_creds(), and possibly should be
folded into that. commit_creds() should take care of protecting
__sigqueue_alloc().
(7) [sg]et[ug]id() and co and [sg]et_current_groups.
The set functions now all use prepare_creds(), commit_creds() and
abort_creds() to build and check a new set of credentials before applying
it.
security_task_set[ug]id() is called inside the prepared section. This
guarantees that nothing else will affect the creds until we've finished.
The calling of set_dumpable() has been moved into commit_creds().
Much of the functionality of set_user() has been moved into
commit_creds().
The get functions all simply access the data directly.
(8) security_task_prctl() and cap_task_prctl().
security_task_prctl() has been modified to return -ENOSYS if it doesn't
want to handle a function, or otherwise return the return value directly
rather than through an argument.
Additionally, cap_task_prctl() now prepares a new set of credentials, even
if it doesn't end up using it.
(9) Keyrings.
A number of changes have been made to the keyrings code:
(a) switch_uid_keyring(), copy_keys(), exit_keys() and suid_keys() have
all been dropped and built in to the credentials functions directly.
They may want separating out again later.
(b) key_alloc() and search_process_keyrings() now take a cred pointer
rather than a task pointer to specify the security context.
(c) copy_creds() gives a new thread within the same thread group a new
thread keyring if its parent had one, otherwise it discards the thread
keyring.
(d) The authorisation key now points directly to the credentials to extend
the search into rather pointing to the task that carries them.
(e) Installing thread, process or session keyrings causes a new set of
credentials to be created, even though it's not strictly necessary for
process or session keyrings (they're shared).
(10) Usermode helper.
The usermode helper code now carries a cred struct pointer in its
subprocess_info struct instead of a new session keyring pointer. This set
of credentials is derived from init_cred and installed on the new process
after it has been cloned.
call_usermodehelper_setup() allocates the new credentials and
call_usermodehelper_freeinfo() discards them if they haven't been used. A
special cred function (prepare_usermodeinfo_creds()) is provided
specifically for call_usermodehelper_setup() to call.
call_usermodehelper_setkeys() adjusts the credentials to sport the
supplied keyring as the new session keyring.
(11) SELinux.
SELinux has a number of changes, in addition to those to support the LSM
interface changes mentioned above:
(a) selinux_setprocattr() no longer does its check for whether the
current ptracer can access processes with the new SID inside the lock
that covers getting the ptracer's SID. Whilst this lock ensures that
the check is done with the ptracer pinned, the result is only valid
until the lock is released, so there's no point doing it inside the
lock.
(12) is_single_threaded().
This function has been extracted from selinux_setprocattr() and put into
a file of its own in the lib/ directory as join_session_keyring() now
wants to use it too.
The code in SELinux just checked to see whether a task shared mm_structs
with other tasks (CLONE_VM), but that isn't good enough. We really want
to know if they're part of the same thread group (CLONE_THREAD).
(13) nfsd.
The NFS server daemon now has to use the COW credentials to set the
credentials it is going to use. It really needs to pass the credentials
down to the functions it calls, but it can't do that until other patches
in this series have been applied.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Signed-off-by: James Morris <jmorris@namei.org>
2008-11-13 23:39:23 +00:00
|
|
|
const struct cred *old_cred;
|
|
|
|
struct cred *override_cred;
|
2008-07-22 13:59:21 +00:00
|
|
|
struct path path;
|
2008-07-22 12:09:30 +00:00
|
|
|
struct inode *inode;
|
2005-04-16 22:20:36 +00:00
|
|
|
int res;
|
2012-12-11 17:10:11 +00:00
|
|
|
unsigned int lookup_flags = LOOKUP_FOLLOW;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
|
|
|
|
return -EINVAL;
|
|
|
|
|
CRED: Inaugurate COW credentials
Inaugurate copy-on-write credentials management. This uses RCU to manage the
credentials pointer in the task_struct with respect to accesses by other tasks.
A process may only modify its own credentials, and so does not need locking to
access or modify its own credentials.
A mutex (cred_replace_mutex) is added to the task_struct to control the effect
of PTRACE_ATTACHED on credential calculations, particularly with respect to
execve().
With this patch, the contents of an active credentials struct may not be
changed directly; rather a new set of credentials must be prepared, modified
and committed using something like the following sequence of events:
struct cred *new = prepare_creds();
int ret = blah(new);
if (ret < 0) {
abort_creds(new);
return ret;
}
return commit_creds(new);
There are some exceptions to this rule: the keyrings pointed to by the active
credentials may be instantiated - keyrings violate the COW rule as managing
COW keyrings is tricky, given that it is possible for a task to directly alter
the keys in a keyring in use by another task.
To help enforce this, various pointers to sets of credentials, such as those in
the task_struct, are declared const. The purpose of this is compile-time
discouragement of altering credentials through those pointers. Once a set of
credentials has been made public through one of these pointers, it may not be
modified, except under special circumstances:
(1) Its reference count may incremented and decremented.
(2) The keyrings to which it points may be modified, but not replaced.
The only safe way to modify anything else is to create a replacement and commit
using the functions described in Documentation/credentials.txt (which will be
added by a later patch).
This patch and the preceding patches have been tested with the LTP SELinux
testsuite.
This patch makes several logical sets of alteration:
(1) execve().
This now prepares and commits credentials in various places in the
security code rather than altering the current creds directly.
(2) Temporary credential overrides.
do_coredump() and sys_faccessat() now prepare their own credentials and
temporarily override the ones currently on the acting thread, whilst
preventing interference from other threads by holding cred_replace_mutex
on the thread being dumped.
This will be replaced in a future patch by something that hands down the
credentials directly to the functions being called, rather than altering
the task's objective credentials.
(3) LSM interface.
A number of functions have been changed, added or removed:
(*) security_capset_check(), ->capset_check()
(*) security_capset_set(), ->capset_set()
Removed in favour of security_capset().
(*) security_capset(), ->capset()
New. This is passed a pointer to the new creds, a pointer to the old
creds and the proposed capability sets. It should fill in the new
creds or return an error. All pointers, barring the pointer to the
new creds, are now const.
(*) security_bprm_apply_creds(), ->bprm_apply_creds()
Changed; now returns a value, which will cause the process to be
killed if it's an error.
(*) security_task_alloc(), ->task_alloc_security()
Removed in favour of security_prepare_creds().
(*) security_cred_free(), ->cred_free()
New. Free security data attached to cred->security.
(*) security_prepare_creds(), ->cred_prepare()
New. Duplicate any security data attached to cred->security.
(*) security_commit_creds(), ->cred_commit()
New. Apply any security effects for the upcoming installation of new
security by commit_creds().
(*) security_task_post_setuid(), ->task_post_setuid()
Removed in favour of security_task_fix_setuid().
(*) security_task_fix_setuid(), ->task_fix_setuid()
Fix up the proposed new credentials for setuid(). This is used by
cap_set_fix_setuid() to implicitly adjust capabilities in line with
setuid() changes. Changes are made to the new credentials, rather
than the task itself as in security_task_post_setuid().
(*) security_task_reparent_to_init(), ->task_reparent_to_init()
Removed. Instead the task being reparented to init is referred
directly to init's credentials.
NOTE! This results in the loss of some state: SELinux's osid no
longer records the sid of the thread that forked it.
(*) security_key_alloc(), ->key_alloc()
(*) security_key_permission(), ->key_permission()
Changed. These now take cred pointers rather than task pointers to
refer to the security context.
(4) sys_capset().
This has been simplified and uses less locking. The LSM functions it
calls have been merged.
(5) reparent_to_kthreadd().
This gives the current thread the same credentials as init by simply using
commit_thread() to point that way.
(6) __sigqueue_alloc() and switch_uid()
__sigqueue_alloc() can't stop the target task from changing its creds
beneath it, so this function gets a reference to the currently applicable
user_struct which it then passes into the sigqueue struct it returns if
successful.
switch_uid() is now called from commit_creds(), and possibly should be
folded into that. commit_creds() should take care of protecting
__sigqueue_alloc().
(7) [sg]et[ug]id() and co and [sg]et_current_groups.
The set functions now all use prepare_creds(), commit_creds() and
abort_creds() to build and check a new set of credentials before applying
it.
security_task_set[ug]id() is called inside the prepared section. This
guarantees that nothing else will affect the creds until we've finished.
The calling of set_dumpable() has been moved into commit_creds().
Much of the functionality of set_user() has been moved into
commit_creds().
The get functions all simply access the data directly.
(8) security_task_prctl() and cap_task_prctl().
security_task_prctl() has been modified to return -ENOSYS if it doesn't
want to handle a function, or otherwise return the return value directly
rather than through an argument.
Additionally, cap_task_prctl() now prepares a new set of credentials, even
if it doesn't end up using it.
(9) Keyrings.
A number of changes have been made to the keyrings code:
(a) switch_uid_keyring(), copy_keys(), exit_keys() and suid_keys() have
all been dropped and built in to the credentials functions directly.
They may want separating out again later.
(b) key_alloc() and search_process_keyrings() now take a cred pointer
rather than a task pointer to specify the security context.
(c) copy_creds() gives a new thread within the same thread group a new
thread keyring if its parent had one, otherwise it discards the thread
keyring.
(d) The authorisation key now points directly to the credentials to extend
the search into rather pointing to the task that carries them.
(e) Installing thread, process or session keyrings causes a new set of
credentials to be created, even though it's not strictly necessary for
process or session keyrings (they're shared).
(10) Usermode helper.
The usermode helper code now carries a cred struct pointer in its
subprocess_info struct instead of a new session keyring pointer. This set
of credentials is derived from init_cred and installed on the new process
after it has been cloned.
call_usermodehelper_setup() allocates the new credentials and
call_usermodehelper_freeinfo() discards them if they haven't been used. A
special cred function (prepare_usermodeinfo_creds()) is provided
specifically for call_usermodehelper_setup() to call.
call_usermodehelper_setkeys() adjusts the credentials to sport the
supplied keyring as the new session keyring.
(11) SELinux.
SELinux has a number of changes, in addition to those to support the LSM
interface changes mentioned above:
(a) selinux_setprocattr() no longer does its check for whether the
current ptracer can access processes with the new SID inside the lock
that covers getting the ptracer's SID. Whilst this lock ensures that
the check is done with the ptracer pinned, the result is only valid
until the lock is released, so there's no point doing it inside the
lock.
(12) is_single_threaded().
This function has been extracted from selinux_setprocattr() and put into
a file of its own in the lib/ directory as join_session_keyring() now
wants to use it too.
The code in SELinux just checked to see whether a task shared mm_structs
with other tasks (CLONE_VM), but that isn't good enough. We really want
to know if they're part of the same thread group (CLONE_THREAD).
(13) nfsd.
The NFS server daemon now has to use the COW credentials to set the
credentials it is going to use. It really needs to pass the credentials
down to the functions it calls, but it can't do that until other patches
in this series have been applied.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Signed-off-by: James Morris <jmorris@namei.org>
2008-11-13 23:39:23 +00:00
|
|
|
override_cred = prepare_creds();
|
|
|
|
if (!override_cred)
|
|
|
|
return -ENOMEM;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
CRED: Inaugurate COW credentials
Inaugurate copy-on-write credentials management. This uses RCU to manage the
credentials pointer in the task_struct with respect to accesses by other tasks.
A process may only modify its own credentials, and so does not need locking to
access or modify its own credentials.
A mutex (cred_replace_mutex) is added to the task_struct to control the effect
of PTRACE_ATTACHED on credential calculations, particularly with respect to
execve().
With this patch, the contents of an active credentials struct may not be
changed directly; rather a new set of credentials must be prepared, modified
and committed using something like the following sequence of events:
struct cred *new = prepare_creds();
int ret = blah(new);
if (ret < 0) {
abort_creds(new);
return ret;
}
return commit_creds(new);
There are some exceptions to this rule: the keyrings pointed to by the active
credentials may be instantiated - keyrings violate the COW rule as managing
COW keyrings is tricky, given that it is possible for a task to directly alter
the keys in a keyring in use by another task.
To help enforce this, various pointers to sets of credentials, such as those in
the task_struct, are declared const. The purpose of this is compile-time
discouragement of altering credentials through those pointers. Once a set of
credentials has been made public through one of these pointers, it may not be
modified, except under special circumstances:
(1) Its reference count may incremented and decremented.
(2) The keyrings to which it points may be modified, but not replaced.
The only safe way to modify anything else is to create a replacement and commit
using the functions described in Documentation/credentials.txt (which will be
added by a later patch).
This patch and the preceding patches have been tested with the LTP SELinux
testsuite.
This patch makes several logical sets of alteration:
(1) execve().
This now prepares and commits credentials in various places in the
security code rather than altering the current creds directly.
(2) Temporary credential overrides.
do_coredump() and sys_faccessat() now prepare their own credentials and
temporarily override the ones currently on the acting thread, whilst
preventing interference from other threads by holding cred_replace_mutex
on the thread being dumped.
This will be replaced in a future patch by something that hands down the
credentials directly to the functions being called, rather than altering
the task's objective credentials.
(3) LSM interface.
A number of functions have been changed, added or removed:
(*) security_capset_check(), ->capset_check()
(*) security_capset_set(), ->capset_set()
Removed in favour of security_capset().
(*) security_capset(), ->capset()
New. This is passed a pointer to the new creds, a pointer to the old
creds and the proposed capability sets. It should fill in the new
creds or return an error. All pointers, barring the pointer to the
new creds, are now const.
(*) security_bprm_apply_creds(), ->bprm_apply_creds()
Changed; now returns a value, which will cause the process to be
killed if it's an error.
(*) security_task_alloc(), ->task_alloc_security()
Removed in favour of security_prepare_creds().
(*) security_cred_free(), ->cred_free()
New. Free security data attached to cred->security.
(*) security_prepare_creds(), ->cred_prepare()
New. Duplicate any security data attached to cred->security.
(*) security_commit_creds(), ->cred_commit()
New. Apply any security effects for the upcoming installation of new
security by commit_creds().
(*) security_task_post_setuid(), ->task_post_setuid()
Removed in favour of security_task_fix_setuid().
(*) security_task_fix_setuid(), ->task_fix_setuid()
Fix up the proposed new credentials for setuid(). This is used by
cap_set_fix_setuid() to implicitly adjust capabilities in line with
setuid() changes. Changes are made to the new credentials, rather
than the task itself as in security_task_post_setuid().
(*) security_task_reparent_to_init(), ->task_reparent_to_init()
Removed. Instead the task being reparented to init is referred
directly to init's credentials.
NOTE! This results in the loss of some state: SELinux's osid no
longer records the sid of the thread that forked it.
(*) security_key_alloc(), ->key_alloc()
(*) security_key_permission(), ->key_permission()
Changed. These now take cred pointers rather than task pointers to
refer to the security context.
(4) sys_capset().
This has been simplified and uses less locking. The LSM functions it
calls have been merged.
(5) reparent_to_kthreadd().
This gives the current thread the same credentials as init by simply using
commit_thread() to point that way.
(6) __sigqueue_alloc() and switch_uid()
__sigqueue_alloc() can't stop the target task from changing its creds
beneath it, so this function gets a reference to the currently applicable
user_struct which it then passes into the sigqueue struct it returns if
successful.
switch_uid() is now called from commit_creds(), and possibly should be
folded into that. commit_creds() should take care of protecting
__sigqueue_alloc().
(7) [sg]et[ug]id() and co and [sg]et_current_groups.
The set functions now all use prepare_creds(), commit_creds() and
abort_creds() to build and check a new set of credentials before applying
it.
security_task_set[ug]id() is called inside the prepared section. This
guarantees that nothing else will affect the creds until we've finished.
The calling of set_dumpable() has been moved into commit_creds().
Much of the functionality of set_user() has been moved into
commit_creds().
The get functions all simply access the data directly.
(8) security_task_prctl() and cap_task_prctl().
security_task_prctl() has been modified to return -ENOSYS if it doesn't
want to handle a function, or otherwise return the return value directly
rather than through an argument.
Additionally, cap_task_prctl() now prepares a new set of credentials, even
if it doesn't end up using it.
(9) Keyrings.
A number of changes have been made to the keyrings code:
(a) switch_uid_keyring(), copy_keys(), exit_keys() and suid_keys() have
all been dropped and built in to the credentials functions directly.
They may want separating out again later.
(b) key_alloc() and search_process_keyrings() now take a cred pointer
rather than a task pointer to specify the security context.
(c) copy_creds() gives a new thread within the same thread group a new
thread keyring if its parent had one, otherwise it discards the thread
keyring.
(d) The authorisation key now points directly to the credentials to extend
the search into rather pointing to the task that carries them.
(e) Installing thread, process or session keyrings causes a new set of
credentials to be created, even though it's not strictly necessary for
process or session keyrings (they're shared).
(10) Usermode helper.
The usermode helper code now carries a cred struct pointer in its
subprocess_info struct instead of a new session keyring pointer. This set
of credentials is derived from init_cred and installed on the new process
after it has been cloned.
call_usermodehelper_setup() allocates the new credentials and
call_usermodehelper_freeinfo() discards them if they haven't been used. A
special cred function (prepare_usermodeinfo_creds()) is provided
specifically for call_usermodehelper_setup() to call.
call_usermodehelper_setkeys() adjusts the credentials to sport the
supplied keyring as the new session keyring.
(11) SELinux.
SELinux has a number of changes, in addition to those to support the LSM
interface changes mentioned above:
(a) selinux_setprocattr() no longer does its check for whether the
current ptracer can access processes with the new SID inside the lock
that covers getting the ptracer's SID. Whilst this lock ensures that
the check is done with the ptracer pinned, the result is only valid
until the lock is released, so there's no point doing it inside the
lock.
(12) is_single_threaded().
This function has been extracted from selinux_setprocattr() and put into
a file of its own in the lib/ directory as join_session_keyring() now
wants to use it too.
The code in SELinux just checked to see whether a task shared mm_structs
with other tasks (CLONE_VM), but that isn't good enough. We really want
to know if they're part of the same thread group (CLONE_THREAD).
(13) nfsd.
The NFS server daemon now has to use the COW credentials to set the
credentials it is going to use. It really needs to pass the credentials
down to the functions it calls, but it can't do that until other patches
in this series have been applied.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Signed-off-by: James Morris <jmorris@namei.org>
2008-11-13 23:39:23 +00:00
|
|
|
override_cred->fsuid = override_cred->uid;
|
|
|
|
override_cred->fsgid = override_cred->gid;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-07-04 16:59:58 +00:00
|
|
|
if (!issecure(SECURE_NO_SETUID_FIXUP)) {
|
2008-11-13 23:39:14 +00:00
|
|
|
/* Clear the capabilities if we switch to a non-root user */
|
2012-02-08 00:45:47 +00:00
|
|
|
kuid_t root_uid = make_kuid(override_cred->user_ns, 0);
|
|
|
|
if (!uid_eq(override_cred->uid, root_uid))
|
CRED: Inaugurate COW credentials
Inaugurate copy-on-write credentials management. This uses RCU to manage the
credentials pointer in the task_struct with respect to accesses by other tasks.
A process may only modify its own credentials, and so does not need locking to
access or modify its own credentials.
A mutex (cred_replace_mutex) is added to the task_struct to control the effect
of PTRACE_ATTACHED on credential calculations, particularly with respect to
execve().
With this patch, the contents of an active credentials struct may not be
changed directly; rather a new set of credentials must be prepared, modified
and committed using something like the following sequence of events:
struct cred *new = prepare_creds();
int ret = blah(new);
if (ret < 0) {
abort_creds(new);
return ret;
}
return commit_creds(new);
There are some exceptions to this rule: the keyrings pointed to by the active
credentials may be instantiated - keyrings violate the COW rule as managing
COW keyrings is tricky, given that it is possible for a task to directly alter
the keys in a keyring in use by another task.
To help enforce this, various pointers to sets of credentials, such as those in
the task_struct, are declared const. The purpose of this is compile-time
discouragement of altering credentials through those pointers. Once a set of
credentials has been made public through one of these pointers, it may not be
modified, except under special circumstances:
(1) Its reference count may incremented and decremented.
(2) The keyrings to which it points may be modified, but not replaced.
The only safe way to modify anything else is to create a replacement and commit
using the functions described in Documentation/credentials.txt (which will be
added by a later patch).
This patch and the preceding patches have been tested with the LTP SELinux
testsuite.
This patch makes several logical sets of alteration:
(1) execve().
This now prepares and commits credentials in various places in the
security code rather than altering the current creds directly.
(2) Temporary credential overrides.
do_coredump() and sys_faccessat() now prepare their own credentials and
temporarily override the ones currently on the acting thread, whilst
preventing interference from other threads by holding cred_replace_mutex
on the thread being dumped.
This will be replaced in a future patch by something that hands down the
credentials directly to the functions being called, rather than altering
the task's objective credentials.
(3) LSM interface.
A number of functions have been changed, added or removed:
(*) security_capset_check(), ->capset_check()
(*) security_capset_set(), ->capset_set()
Removed in favour of security_capset().
(*) security_capset(), ->capset()
New. This is passed a pointer to the new creds, a pointer to the old
creds and the proposed capability sets. It should fill in the new
creds or return an error. All pointers, barring the pointer to the
new creds, are now const.
(*) security_bprm_apply_creds(), ->bprm_apply_creds()
Changed; now returns a value, which will cause the process to be
killed if it's an error.
(*) security_task_alloc(), ->task_alloc_security()
Removed in favour of security_prepare_creds().
(*) security_cred_free(), ->cred_free()
New. Free security data attached to cred->security.
(*) security_prepare_creds(), ->cred_prepare()
New. Duplicate any security data attached to cred->security.
(*) security_commit_creds(), ->cred_commit()
New. Apply any security effects for the upcoming installation of new
security by commit_creds().
(*) security_task_post_setuid(), ->task_post_setuid()
Removed in favour of security_task_fix_setuid().
(*) security_task_fix_setuid(), ->task_fix_setuid()
Fix up the proposed new credentials for setuid(). This is used by
cap_set_fix_setuid() to implicitly adjust capabilities in line with
setuid() changes. Changes are made to the new credentials, rather
than the task itself as in security_task_post_setuid().
(*) security_task_reparent_to_init(), ->task_reparent_to_init()
Removed. Instead the task being reparented to init is referred
directly to init's credentials.
NOTE! This results in the loss of some state: SELinux's osid no
longer records the sid of the thread that forked it.
(*) security_key_alloc(), ->key_alloc()
(*) security_key_permission(), ->key_permission()
Changed. These now take cred pointers rather than task pointers to
refer to the security context.
(4) sys_capset().
This has been simplified and uses less locking. The LSM functions it
calls have been merged.
(5) reparent_to_kthreadd().
This gives the current thread the same credentials as init by simply using
commit_thread() to point that way.
(6) __sigqueue_alloc() and switch_uid()
__sigqueue_alloc() can't stop the target task from changing its creds
beneath it, so this function gets a reference to the currently applicable
user_struct which it then passes into the sigqueue struct it returns if
successful.
switch_uid() is now called from commit_creds(), and possibly should be
folded into that. commit_creds() should take care of protecting
__sigqueue_alloc().
(7) [sg]et[ug]id() and co and [sg]et_current_groups.
The set functions now all use prepare_creds(), commit_creds() and
abort_creds() to build and check a new set of credentials before applying
it.
security_task_set[ug]id() is called inside the prepared section. This
guarantees that nothing else will affect the creds until we've finished.
The calling of set_dumpable() has been moved into commit_creds().
Much of the functionality of set_user() has been moved into
commit_creds().
The get functions all simply access the data directly.
(8) security_task_prctl() and cap_task_prctl().
security_task_prctl() has been modified to return -ENOSYS if it doesn't
want to handle a function, or otherwise return the return value directly
rather than through an argument.
Additionally, cap_task_prctl() now prepares a new set of credentials, even
if it doesn't end up using it.
(9) Keyrings.
A number of changes have been made to the keyrings code:
(a) switch_uid_keyring(), copy_keys(), exit_keys() and suid_keys() have
all been dropped and built in to the credentials functions directly.
They may want separating out again later.
(b) key_alloc() and search_process_keyrings() now take a cred pointer
rather than a task pointer to specify the security context.
(c) copy_creds() gives a new thread within the same thread group a new
thread keyring if its parent had one, otherwise it discards the thread
keyring.
(d) The authorisation key now points directly to the credentials to extend
the search into rather pointing to the task that carries them.
(e) Installing thread, process or session keyrings causes a new set of
credentials to be created, even though it's not strictly necessary for
process or session keyrings (they're shared).
(10) Usermode helper.
The usermode helper code now carries a cred struct pointer in its
subprocess_info struct instead of a new session keyring pointer. This set
of credentials is derived from init_cred and installed on the new process
after it has been cloned.
call_usermodehelper_setup() allocates the new credentials and
call_usermodehelper_freeinfo() discards them if they haven't been used. A
special cred function (prepare_usermodeinfo_creds()) is provided
specifically for call_usermodehelper_setup() to call.
call_usermodehelper_setkeys() adjusts the credentials to sport the
supplied keyring as the new session keyring.
(11) SELinux.
SELinux has a number of changes, in addition to those to support the LSM
interface changes mentioned above:
(a) selinux_setprocattr() no longer does its check for whether the
current ptracer can access processes with the new SID inside the lock
that covers getting the ptracer's SID. Whilst this lock ensures that
the check is done with the ptracer pinned, the result is only valid
until the lock is released, so there's no point doing it inside the
lock.
(12) is_single_threaded().
This function has been extracted from selinux_setprocattr() and put into
a file of its own in the lib/ directory as join_session_keyring() now
wants to use it too.
The code in SELinux just checked to see whether a task shared mm_structs
with other tasks (CLONE_VM), but that isn't good enough. We really want
to know if they're part of the same thread group (CLONE_THREAD).
(13) nfsd.
The NFS server daemon now has to use the COW credentials to set the
credentials it is going to use. It really needs to pass the credentials
down to the functions it calls, but it can't do that until other patches
in this series have been applied.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Signed-off-by: James Morris <jmorris@namei.org>
2008-11-13 23:39:23 +00:00
|
|
|
cap_clear(override_cred->cap_effective);
|
2008-07-04 16:59:58 +00:00
|
|
|
else
|
CRED: Inaugurate COW credentials
Inaugurate copy-on-write credentials management. This uses RCU to manage the
credentials pointer in the task_struct with respect to accesses by other tasks.
A process may only modify its own credentials, and so does not need locking to
access or modify its own credentials.
A mutex (cred_replace_mutex) is added to the task_struct to control the effect
of PTRACE_ATTACHED on credential calculations, particularly with respect to
execve().
With this patch, the contents of an active credentials struct may not be
changed directly; rather a new set of credentials must be prepared, modified
and committed using something like the following sequence of events:
struct cred *new = prepare_creds();
int ret = blah(new);
if (ret < 0) {
abort_creds(new);
return ret;
}
return commit_creds(new);
There are some exceptions to this rule: the keyrings pointed to by the active
credentials may be instantiated - keyrings violate the COW rule as managing
COW keyrings is tricky, given that it is possible for a task to directly alter
the keys in a keyring in use by another task.
To help enforce this, various pointers to sets of credentials, such as those in
the task_struct, are declared const. The purpose of this is compile-time
discouragement of altering credentials through those pointers. Once a set of
credentials has been made public through one of these pointers, it may not be
modified, except under special circumstances:
(1) Its reference count may incremented and decremented.
(2) The keyrings to which it points may be modified, but not replaced.
The only safe way to modify anything else is to create a replacement and commit
using the functions described in Documentation/credentials.txt (which will be
added by a later patch).
This patch and the preceding patches have been tested with the LTP SELinux
testsuite.
This patch makes several logical sets of alteration:
(1) execve().
This now prepares and commits credentials in various places in the
security code rather than altering the current creds directly.
(2) Temporary credential overrides.
do_coredump() and sys_faccessat() now prepare their own credentials and
temporarily override the ones currently on the acting thread, whilst
preventing interference from other threads by holding cred_replace_mutex
on the thread being dumped.
This will be replaced in a future patch by something that hands down the
credentials directly to the functions being called, rather than altering
the task's objective credentials.
(3) LSM interface.
A number of functions have been changed, added or removed:
(*) security_capset_check(), ->capset_check()
(*) security_capset_set(), ->capset_set()
Removed in favour of security_capset().
(*) security_capset(), ->capset()
New. This is passed a pointer to the new creds, a pointer to the old
creds and the proposed capability sets. It should fill in the new
creds or return an error. All pointers, barring the pointer to the
new creds, are now const.
(*) security_bprm_apply_creds(), ->bprm_apply_creds()
Changed; now returns a value, which will cause the process to be
killed if it's an error.
(*) security_task_alloc(), ->task_alloc_security()
Removed in favour of security_prepare_creds().
(*) security_cred_free(), ->cred_free()
New. Free security data attached to cred->security.
(*) security_prepare_creds(), ->cred_prepare()
New. Duplicate any security data attached to cred->security.
(*) security_commit_creds(), ->cred_commit()
New. Apply any security effects for the upcoming installation of new
security by commit_creds().
(*) security_task_post_setuid(), ->task_post_setuid()
Removed in favour of security_task_fix_setuid().
(*) security_task_fix_setuid(), ->task_fix_setuid()
Fix up the proposed new credentials for setuid(). This is used by
cap_set_fix_setuid() to implicitly adjust capabilities in line with
setuid() changes. Changes are made to the new credentials, rather
than the task itself as in security_task_post_setuid().
(*) security_task_reparent_to_init(), ->task_reparent_to_init()
Removed. Instead the task being reparented to init is referred
directly to init's credentials.
NOTE! This results in the loss of some state: SELinux's osid no
longer records the sid of the thread that forked it.
(*) security_key_alloc(), ->key_alloc()
(*) security_key_permission(), ->key_permission()
Changed. These now take cred pointers rather than task pointers to
refer to the security context.
(4) sys_capset().
This has been simplified and uses less locking. The LSM functions it
calls have been merged.
(5) reparent_to_kthreadd().
This gives the current thread the same credentials as init by simply using
commit_thread() to point that way.
(6) __sigqueue_alloc() and switch_uid()
__sigqueue_alloc() can't stop the target task from changing its creds
beneath it, so this function gets a reference to the currently applicable
user_struct which it then passes into the sigqueue struct it returns if
successful.
switch_uid() is now called from commit_creds(), and possibly should be
folded into that. commit_creds() should take care of protecting
__sigqueue_alloc().
(7) [sg]et[ug]id() and co and [sg]et_current_groups.
The set functions now all use prepare_creds(), commit_creds() and
abort_creds() to build and check a new set of credentials before applying
it.
security_task_set[ug]id() is called inside the prepared section. This
guarantees that nothing else will affect the creds until we've finished.
The calling of set_dumpable() has been moved into commit_creds().
Much of the functionality of set_user() has been moved into
commit_creds().
The get functions all simply access the data directly.
(8) security_task_prctl() and cap_task_prctl().
security_task_prctl() has been modified to return -ENOSYS if it doesn't
want to handle a function, or otherwise return the return value directly
rather than through an argument.
Additionally, cap_task_prctl() now prepares a new set of credentials, even
if it doesn't end up using it.
(9) Keyrings.
A number of changes have been made to the keyrings code:
(a) switch_uid_keyring(), copy_keys(), exit_keys() and suid_keys() have
all been dropped and built in to the credentials functions directly.
They may want separating out again later.
(b) key_alloc() and search_process_keyrings() now take a cred pointer
rather than a task pointer to specify the security context.
(c) copy_creds() gives a new thread within the same thread group a new
thread keyring if its parent had one, otherwise it discards the thread
keyring.
(d) The authorisation key now points directly to the credentials to extend
the search into rather pointing to the task that carries them.
(e) Installing thread, process or session keyrings causes a new set of
credentials to be created, even though it's not strictly necessary for
process or session keyrings (they're shared).
(10) Usermode helper.
The usermode helper code now carries a cred struct pointer in its
subprocess_info struct instead of a new session keyring pointer. This set
of credentials is derived from init_cred and installed on the new process
after it has been cloned.
call_usermodehelper_setup() allocates the new credentials and
call_usermodehelper_freeinfo() discards them if they haven't been used. A
special cred function (prepare_usermodeinfo_creds()) is provided
specifically for call_usermodehelper_setup() to call.
call_usermodehelper_setkeys() adjusts the credentials to sport the
supplied keyring as the new session keyring.
(11) SELinux.
SELinux has a number of changes, in addition to those to support the LSM
interface changes mentioned above:
(a) selinux_setprocattr() no longer does its check for whether the
current ptracer can access processes with the new SID inside the lock
that covers getting the ptracer's SID. Whilst this lock ensures that
the check is done with the ptracer pinned, the result is only valid
until the lock is released, so there's no point doing it inside the
lock.
(12) is_single_threaded().
This function has been extracted from selinux_setprocattr() and put into
a file of its own in the lib/ directory as join_session_keyring() now
wants to use it too.
The code in SELinux just checked to see whether a task shared mm_structs
with other tasks (CLONE_VM), but that isn't good enough. We really want
to know if they're part of the same thread group (CLONE_THREAD).
(13) nfsd.
The NFS server daemon now has to use the COW credentials to set the
credentials it is going to use. It really needs to pass the credentials
down to the functions it calls, but it can't do that until other patches
in this series have been applied.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Signed-off-by: James Morris <jmorris@namei.org>
2008-11-13 23:39:23 +00:00
|
|
|
override_cred->cap_effective =
|
|
|
|
override_cred->cap_permitted;
|
2008-07-04 16:59:58 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
access: avoid the RCU grace period for the temporary subjective credentials
It turns out that 'access()' (and 'faccessat()') can cause a lot of RCU
work because it installs a temporary credential that gets allocated and
freed for each system call.
The allocation and freeing overhead is mostly benign, but because
credentials can be accessed under the RCU read lock, the freeing
involves a RCU grace period.
Which is not a huge deal normally, but if you have a lot of access()
calls, this causes a fair amount of seconday damage: instead of having a
nice alloc/free patterns that hits in hot per-CPU slab caches, you have
all those delayed free's, and on big machines with hundreds of cores,
the RCU overhead can end up being enormous.
But it turns out that all of this is entirely unnecessary. Exactly
because access() only installs the credential as the thread-local
subjective credential, the temporary cred pointer doesn't actually need
to be RCU free'd at all. Once we're done using it, we can just free it
synchronously and avoid all the RCU overhead.
So add a 'non_rcu' flag to 'struct cred', which can be set by users that
know they only use it in non-RCU context (there are other potential
users for this). We can make it a union with the rcu freeing list head
that we need for the RCU case, so this doesn't need any extra storage.
Note that this also makes 'get_current_cred()' clear the new non_rcu
flag, in case we have filesystems that take a long-term reference to the
cred and then expect the RCU delayed freeing afterwards. It's not
entirely clear that this is required, but it makes for clear semantics:
the subjective cred remains non-RCU as long as you only access it
synchronously using the thread-local accessors, but you _can_ use it as
a generic cred if you want to.
It is possible that we should just remove the whole RCU markings for
->cred entirely. Only ->real_cred is really supposed to be accessed
through RCU, and the long-term cred copies that nfs uses might want to
explicitly re-enable RCU freeing if required, rather than have
get_current_cred() do it implicitly.
But this is a "minimal semantic changes" change for the immediate
problem.
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Eric Dumazet <edumazet@google.com>
Acked-by: Paul E. McKenney <paulmck@linux.ibm.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Jan Glauber <jglauber@marvell.com>
Cc: Jiri Kosina <jikos@kernel.org>
Cc: Jayachandran Chandrasekharan Nair <jnair@marvell.com>
Cc: Greg KH <greg@kroah.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: David Howells <dhowells@redhat.com>
Cc: Miklos Szeredi <miklos@szeredi.hu>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2019-07-11 16:54:40 +00:00
|
|
|
/*
|
|
|
|
* The new set of credentials can *only* be used in
|
|
|
|
* task-synchronous circumstances, and does not need
|
|
|
|
* RCU freeing, unless somebody then takes a separate
|
|
|
|
* reference to it.
|
|
|
|
*
|
|
|
|
* NOTE! This is _only_ true because this credential
|
|
|
|
* is used purely for override_creds() that installs
|
|
|
|
* it as the subjective cred. Other threads will be
|
|
|
|
* accessing ->real_cred, not the subjective cred.
|
|
|
|
*
|
|
|
|
* If somebody _does_ make a copy of this (using the
|
|
|
|
* 'get_current_cred()' function), that will clear the
|
|
|
|
* non_rcu field, because now that other user may be
|
|
|
|
* expecting RCU freeing. But normal thread-synchronous
|
|
|
|
* cred accesses will keep things non-RCY.
|
|
|
|
*/
|
|
|
|
override_cred->non_rcu = 1;
|
|
|
|
|
CRED: Inaugurate COW credentials
Inaugurate copy-on-write credentials management. This uses RCU to manage the
credentials pointer in the task_struct with respect to accesses by other tasks.
A process may only modify its own credentials, and so does not need locking to
access or modify its own credentials.
A mutex (cred_replace_mutex) is added to the task_struct to control the effect
of PTRACE_ATTACHED on credential calculations, particularly with respect to
execve().
With this patch, the contents of an active credentials struct may not be
changed directly; rather a new set of credentials must be prepared, modified
and committed using something like the following sequence of events:
struct cred *new = prepare_creds();
int ret = blah(new);
if (ret < 0) {
abort_creds(new);
return ret;
}
return commit_creds(new);
There are some exceptions to this rule: the keyrings pointed to by the active
credentials may be instantiated - keyrings violate the COW rule as managing
COW keyrings is tricky, given that it is possible for a task to directly alter
the keys in a keyring in use by another task.
To help enforce this, various pointers to sets of credentials, such as those in
the task_struct, are declared const. The purpose of this is compile-time
discouragement of altering credentials through those pointers. Once a set of
credentials has been made public through one of these pointers, it may not be
modified, except under special circumstances:
(1) Its reference count may incremented and decremented.
(2) The keyrings to which it points may be modified, but not replaced.
The only safe way to modify anything else is to create a replacement and commit
using the functions described in Documentation/credentials.txt (which will be
added by a later patch).
This patch and the preceding patches have been tested with the LTP SELinux
testsuite.
This patch makes several logical sets of alteration:
(1) execve().
This now prepares and commits credentials in various places in the
security code rather than altering the current creds directly.
(2) Temporary credential overrides.
do_coredump() and sys_faccessat() now prepare their own credentials and
temporarily override the ones currently on the acting thread, whilst
preventing interference from other threads by holding cred_replace_mutex
on the thread being dumped.
This will be replaced in a future patch by something that hands down the
credentials directly to the functions being called, rather than altering
the task's objective credentials.
(3) LSM interface.
A number of functions have been changed, added or removed:
(*) security_capset_check(), ->capset_check()
(*) security_capset_set(), ->capset_set()
Removed in favour of security_capset().
(*) security_capset(), ->capset()
New. This is passed a pointer to the new creds, a pointer to the old
creds and the proposed capability sets. It should fill in the new
creds or return an error. All pointers, barring the pointer to the
new creds, are now const.
(*) security_bprm_apply_creds(), ->bprm_apply_creds()
Changed; now returns a value, which will cause the process to be
killed if it's an error.
(*) security_task_alloc(), ->task_alloc_security()
Removed in favour of security_prepare_creds().
(*) security_cred_free(), ->cred_free()
New. Free security data attached to cred->security.
(*) security_prepare_creds(), ->cred_prepare()
New. Duplicate any security data attached to cred->security.
(*) security_commit_creds(), ->cred_commit()
New. Apply any security effects for the upcoming installation of new
security by commit_creds().
(*) security_task_post_setuid(), ->task_post_setuid()
Removed in favour of security_task_fix_setuid().
(*) security_task_fix_setuid(), ->task_fix_setuid()
Fix up the proposed new credentials for setuid(). This is used by
cap_set_fix_setuid() to implicitly adjust capabilities in line with
setuid() changes. Changes are made to the new credentials, rather
than the task itself as in security_task_post_setuid().
(*) security_task_reparent_to_init(), ->task_reparent_to_init()
Removed. Instead the task being reparented to init is referred
directly to init's credentials.
NOTE! This results in the loss of some state: SELinux's osid no
longer records the sid of the thread that forked it.
(*) security_key_alloc(), ->key_alloc()
(*) security_key_permission(), ->key_permission()
Changed. These now take cred pointers rather than task pointers to
refer to the security context.
(4) sys_capset().
This has been simplified and uses less locking. The LSM functions it
calls have been merged.
(5) reparent_to_kthreadd().
This gives the current thread the same credentials as init by simply using
commit_thread() to point that way.
(6) __sigqueue_alloc() and switch_uid()
__sigqueue_alloc() can't stop the target task from changing its creds
beneath it, so this function gets a reference to the currently applicable
user_struct which it then passes into the sigqueue struct it returns if
successful.
switch_uid() is now called from commit_creds(), and possibly should be
folded into that. commit_creds() should take care of protecting
__sigqueue_alloc().
(7) [sg]et[ug]id() and co and [sg]et_current_groups.
The set functions now all use prepare_creds(), commit_creds() and
abort_creds() to build and check a new set of credentials before applying
it.
security_task_set[ug]id() is called inside the prepared section. This
guarantees that nothing else will affect the creds until we've finished.
The calling of set_dumpable() has been moved into commit_creds().
Much of the functionality of set_user() has been moved into
commit_creds().
The get functions all simply access the data directly.
(8) security_task_prctl() and cap_task_prctl().
security_task_prctl() has been modified to return -ENOSYS if it doesn't
want to handle a function, or otherwise return the return value directly
rather than through an argument.
Additionally, cap_task_prctl() now prepares a new set of credentials, even
if it doesn't end up using it.
(9) Keyrings.
A number of changes have been made to the keyrings code:
(a) switch_uid_keyring(), copy_keys(), exit_keys() and suid_keys() have
all been dropped and built in to the credentials functions directly.
They may want separating out again later.
(b) key_alloc() and search_process_keyrings() now take a cred pointer
rather than a task pointer to specify the security context.
(c) copy_creds() gives a new thread within the same thread group a new
thread keyring if its parent had one, otherwise it discards the thread
keyring.
(d) The authorisation key now points directly to the credentials to extend
the search into rather pointing to the task that carries them.
(e) Installing thread, process or session keyrings causes a new set of
credentials to be created, even though it's not strictly necessary for
process or session keyrings (they're shared).
(10) Usermode helper.
The usermode helper code now carries a cred struct pointer in its
subprocess_info struct instead of a new session keyring pointer. This set
of credentials is derived from init_cred and installed on the new process
after it has been cloned.
call_usermodehelper_setup() allocates the new credentials and
call_usermodehelper_freeinfo() discards them if they haven't been used. A
special cred function (prepare_usermodeinfo_creds()) is provided
specifically for call_usermodehelper_setup() to call.
call_usermodehelper_setkeys() adjusts the credentials to sport the
supplied keyring as the new session keyring.
(11) SELinux.
SELinux has a number of changes, in addition to those to support the LSM
interface changes mentioned above:
(a) selinux_setprocattr() no longer does its check for whether the
current ptracer can access processes with the new SID inside the lock
that covers getting the ptracer's SID. Whilst this lock ensures that
the check is done with the ptracer pinned, the result is only valid
until the lock is released, so there's no point doing it inside the
lock.
(12) is_single_threaded().
This function has been extracted from selinux_setprocattr() and put into
a file of its own in the lib/ directory as join_session_keyring() now
wants to use it too.
The code in SELinux just checked to see whether a task shared mm_structs
with other tasks (CLONE_VM), but that isn't good enough. We really want
to know if they're part of the same thread group (CLONE_THREAD).
(13) nfsd.
The NFS server daemon now has to use the COW credentials to set the
credentials it is going to use. It really needs to pass the credentials
down to the functions it calls, but it can't do that until other patches
in this series have been applied.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Signed-off-by: James Morris <jmorris@namei.org>
2008-11-13 23:39:23 +00:00
|
|
|
old_cred = override_creds(override_cred);
|
2012-12-11 17:10:11 +00:00
|
|
|
retry:
|
|
|
|
res = user_path_at(dfd, filename, lookup_flags, &path);
|
2006-10-01 06:29:01 +00:00
|
|
|
if (res)
|
|
|
|
goto out;
|
|
|
|
|
2015-05-06 14:59:00 +00:00
|
|
|
inode = d_backing_inode(path.dentry);
|
2008-07-22 12:09:30 +00:00
|
|
|
|
|
|
|
if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) {
|
2008-07-22 04:02:33 +00:00
|
|
|
/*
|
|
|
|
* MAY_EXEC on regular files is denied if the fs is mounted
|
|
|
|
* with the "noexec" flag.
|
|
|
|
*/
|
|
|
|
res = -EACCES;
|
2015-06-29 19:42:03 +00:00
|
|
|
if (path_noexec(&path))
|
2008-07-22 04:02:33 +00:00
|
|
|
goto out_path_release;
|
|
|
|
}
|
|
|
|
|
2008-07-22 12:09:30 +00:00
|
|
|
res = inode_permission(inode, mode | MAY_ACCESS);
|
2006-10-01 06:29:01 +00:00
|
|
|
/* SuS v2 requires we report a read only fs too */
|
2008-07-22 12:09:30 +00:00
|
|
|
if (res || !(mode & S_IWOTH) || special_file(inode->i_mode))
|
2006-10-01 06:29:01 +00:00
|
|
|
goto out_path_release;
|
2008-02-15 22:37:55 +00:00
|
|
|
/*
|
|
|
|
* This is a rare case where using __mnt_is_readonly()
|
|
|
|
* is OK without a mnt_want/drop_write() pair. Since
|
|
|
|
* no actual write to the fs is performed here, we do
|
|
|
|
* not need to telegraph to that to anyone.
|
|
|
|
*
|
|
|
|
* By doing this, we accept that this access is
|
|
|
|
* inherently racy and know that the fs may change
|
|
|
|
* state before we even see this result.
|
|
|
|
*/
|
2008-07-22 13:59:21 +00:00
|
|
|
if (__mnt_is_readonly(path.mnt))
|
2006-10-01 06:29:01 +00:00
|
|
|
res = -EROFS;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2006-10-01 06:29:01 +00:00
|
|
|
out_path_release:
|
2008-07-22 13:59:21 +00:00
|
|
|
path_put(&path);
|
2012-12-11 17:10:11 +00:00
|
|
|
if (retry_estale(res, lookup_flags)) {
|
|
|
|
lookup_flags |= LOOKUP_REVAL;
|
|
|
|
goto retry;
|
|
|
|
}
|
2006-10-01 06:29:01 +00:00
|
|
|
out:
|
CRED: Inaugurate COW credentials
Inaugurate copy-on-write credentials management. This uses RCU to manage the
credentials pointer in the task_struct with respect to accesses by other tasks.
A process may only modify its own credentials, and so does not need locking to
access or modify its own credentials.
A mutex (cred_replace_mutex) is added to the task_struct to control the effect
of PTRACE_ATTACHED on credential calculations, particularly with respect to
execve().
With this patch, the contents of an active credentials struct may not be
changed directly; rather a new set of credentials must be prepared, modified
and committed using something like the following sequence of events:
struct cred *new = prepare_creds();
int ret = blah(new);
if (ret < 0) {
abort_creds(new);
return ret;
}
return commit_creds(new);
There are some exceptions to this rule: the keyrings pointed to by the active
credentials may be instantiated - keyrings violate the COW rule as managing
COW keyrings is tricky, given that it is possible for a task to directly alter
the keys in a keyring in use by another task.
To help enforce this, various pointers to sets of credentials, such as those in
the task_struct, are declared const. The purpose of this is compile-time
discouragement of altering credentials through those pointers. Once a set of
credentials has been made public through one of these pointers, it may not be
modified, except under special circumstances:
(1) Its reference count may incremented and decremented.
(2) The keyrings to which it points may be modified, but not replaced.
The only safe way to modify anything else is to create a replacement and commit
using the functions described in Documentation/credentials.txt (which will be
added by a later patch).
This patch and the preceding patches have been tested with the LTP SELinux
testsuite.
This patch makes several logical sets of alteration:
(1) execve().
This now prepares and commits credentials in various places in the
security code rather than altering the current creds directly.
(2) Temporary credential overrides.
do_coredump() and sys_faccessat() now prepare their own credentials and
temporarily override the ones currently on the acting thread, whilst
preventing interference from other threads by holding cred_replace_mutex
on the thread being dumped.
This will be replaced in a future patch by something that hands down the
credentials directly to the functions being called, rather than altering
the task's objective credentials.
(3) LSM interface.
A number of functions have been changed, added or removed:
(*) security_capset_check(), ->capset_check()
(*) security_capset_set(), ->capset_set()
Removed in favour of security_capset().
(*) security_capset(), ->capset()
New. This is passed a pointer to the new creds, a pointer to the old
creds and the proposed capability sets. It should fill in the new
creds or return an error. All pointers, barring the pointer to the
new creds, are now const.
(*) security_bprm_apply_creds(), ->bprm_apply_creds()
Changed; now returns a value, which will cause the process to be
killed if it's an error.
(*) security_task_alloc(), ->task_alloc_security()
Removed in favour of security_prepare_creds().
(*) security_cred_free(), ->cred_free()
New. Free security data attached to cred->security.
(*) security_prepare_creds(), ->cred_prepare()
New. Duplicate any security data attached to cred->security.
(*) security_commit_creds(), ->cred_commit()
New. Apply any security effects for the upcoming installation of new
security by commit_creds().
(*) security_task_post_setuid(), ->task_post_setuid()
Removed in favour of security_task_fix_setuid().
(*) security_task_fix_setuid(), ->task_fix_setuid()
Fix up the proposed new credentials for setuid(). This is used by
cap_set_fix_setuid() to implicitly adjust capabilities in line with
setuid() changes. Changes are made to the new credentials, rather
than the task itself as in security_task_post_setuid().
(*) security_task_reparent_to_init(), ->task_reparent_to_init()
Removed. Instead the task being reparented to init is referred
directly to init's credentials.
NOTE! This results in the loss of some state: SELinux's osid no
longer records the sid of the thread that forked it.
(*) security_key_alloc(), ->key_alloc()
(*) security_key_permission(), ->key_permission()
Changed. These now take cred pointers rather than task pointers to
refer to the security context.
(4) sys_capset().
This has been simplified and uses less locking. The LSM functions it
calls have been merged.
(5) reparent_to_kthreadd().
This gives the current thread the same credentials as init by simply using
commit_thread() to point that way.
(6) __sigqueue_alloc() and switch_uid()
__sigqueue_alloc() can't stop the target task from changing its creds
beneath it, so this function gets a reference to the currently applicable
user_struct which it then passes into the sigqueue struct it returns if
successful.
switch_uid() is now called from commit_creds(), and possibly should be
folded into that. commit_creds() should take care of protecting
__sigqueue_alloc().
(7) [sg]et[ug]id() and co and [sg]et_current_groups.
The set functions now all use prepare_creds(), commit_creds() and
abort_creds() to build and check a new set of credentials before applying
it.
security_task_set[ug]id() is called inside the prepared section. This
guarantees that nothing else will affect the creds until we've finished.
The calling of set_dumpable() has been moved into commit_creds().
Much of the functionality of set_user() has been moved into
commit_creds().
The get functions all simply access the data directly.
(8) security_task_prctl() and cap_task_prctl().
security_task_prctl() has been modified to return -ENOSYS if it doesn't
want to handle a function, or otherwise return the return value directly
rather than through an argument.
Additionally, cap_task_prctl() now prepares a new set of credentials, even
if it doesn't end up using it.
(9) Keyrings.
A number of changes have been made to the keyrings code:
(a) switch_uid_keyring(), copy_keys(), exit_keys() and suid_keys() have
all been dropped and built in to the credentials functions directly.
They may want separating out again later.
(b) key_alloc() and search_process_keyrings() now take a cred pointer
rather than a task pointer to specify the security context.
(c) copy_creds() gives a new thread within the same thread group a new
thread keyring if its parent had one, otherwise it discards the thread
keyring.
(d) The authorisation key now points directly to the credentials to extend
the search into rather pointing to the task that carries them.
(e) Installing thread, process or session keyrings causes a new set of
credentials to be created, even though it's not strictly necessary for
process or session keyrings (they're shared).
(10) Usermode helper.
The usermode helper code now carries a cred struct pointer in its
subprocess_info struct instead of a new session keyring pointer. This set
of credentials is derived from init_cred and installed on the new process
after it has been cloned.
call_usermodehelper_setup() allocates the new credentials and
call_usermodehelper_freeinfo() discards them if they haven't been used. A
special cred function (prepare_usermodeinfo_creds()) is provided
specifically for call_usermodehelper_setup() to call.
call_usermodehelper_setkeys() adjusts the credentials to sport the
supplied keyring as the new session keyring.
(11) SELinux.
SELinux has a number of changes, in addition to those to support the LSM
interface changes mentioned above:
(a) selinux_setprocattr() no longer does its check for whether the
current ptracer can access processes with the new SID inside the lock
that covers getting the ptracer's SID. Whilst this lock ensures that
the check is done with the ptracer pinned, the result is only valid
until the lock is released, so there's no point doing it inside the
lock.
(12) is_single_threaded().
This function has been extracted from selinux_setprocattr() and put into
a file of its own in the lib/ directory as join_session_keyring() now
wants to use it too.
The code in SELinux just checked to see whether a task shared mm_structs
with other tasks (CLONE_VM), but that isn't good enough. We really want
to know if they're part of the same thread group (CLONE_THREAD).
(13) nfsd.
The NFS server daemon now has to use the COW credentials to set the
credentials it is going to use. It really needs to pass the credentials
down to the functions it calls, but it can't do that until other patches
in this series have been applied.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Signed-off-by: James Morris <jmorris@namei.org>
2008-11-13 23:39:23 +00:00
|
|
|
revert_creds(old_cred);
|
|
|
|
put_cred(override_cred);
|
2005-04-16 22:20:36 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2018-03-11 10:34:54 +00:00
|
|
|
SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
|
|
|
|
{
|
|
|
|
return do_faccessat(dfd, filename, mode);
|
|
|
|
}
|
|
|
|
|
2009-01-14 13:14:19 +00:00
|
|
|
SYSCALL_DEFINE2(access, const char __user *, filename, int, mode)
|
2006-01-19 01:43:53 +00:00
|
|
|
{
|
2018-03-11 10:34:54 +00:00
|
|
|
return do_faccessat(AT_FDCWD, filename, mode);
|
2006-01-19 01:43:53 +00:00
|
|
|
}
|
|
|
|
|
2018-03-11 10:34:46 +00:00
|
|
|
int ksys_chdir(const char __user *filename)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2008-07-22 13:59:21 +00:00
|
|
|
struct path path;
|
2005-04-16 22:20:36 +00:00
|
|
|
int error;
|
2012-12-11 17:10:12 +00:00
|
|
|
unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
|
|
|
|
retry:
|
|
|
|
error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
|
2010-07-23 15:43:51 +00:00
|
|
|
error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (error)
|
|
|
|
goto dput_and_out;
|
|
|
|
|
2008-07-22 13:59:21 +00:00
|
|
|
set_fs_pwd(current->fs, &path);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
dput_and_out:
|
2008-07-22 13:59:21 +00:00
|
|
|
path_put(&path);
|
2012-12-11 17:10:12 +00:00
|
|
|
if (retry_estale(error, lookup_flags)) {
|
|
|
|
lookup_flags |= LOOKUP_REVAL;
|
|
|
|
goto retry;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
out:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2018-03-11 10:34:46 +00:00
|
|
|
SYSCALL_DEFINE1(chdir, const char __user *, filename)
|
|
|
|
{
|
|
|
|
return ksys_chdir(filename);
|
|
|
|
}
|
|
|
|
|
2009-01-14 13:14:22 +00:00
|
|
|
SYSCALL_DEFINE1(fchdir, unsigned int, fd)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-08-28 16:52:22 +00:00
|
|
|
struct fd f = fdget_raw(fd);
|
2017-04-15 19:58:56 +00:00
|
|
|
int error;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
error = -EBADF;
|
2012-08-28 16:52:22 +00:00
|
|
|
if (!f.file)
|
2005-04-16 22:20:36 +00:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
error = -ENOTDIR;
|
2017-04-15 19:58:56 +00:00
|
|
|
if (!d_can_lookup(f.file->f_path.dentry))
|
2005-04-16 22:20:36 +00:00
|
|
|
goto out_putf;
|
|
|
|
|
2017-04-15 19:58:56 +00:00
|
|
|
error = inode_permission(file_inode(f.file), MAY_EXEC | MAY_CHDIR);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (!error)
|
2012-08-28 16:52:22 +00:00
|
|
|
set_fs_pwd(current->fs, &f.file->f_path);
|
2005-04-16 22:20:36 +00:00
|
|
|
out_putf:
|
2012-08-28 16:52:22 +00:00
|
|
|
fdput(f);
|
2005-04-16 22:20:36 +00:00
|
|
|
out:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2018-03-11 10:34:41 +00:00
|
|
|
int ksys_chroot(const char __user *filename)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2008-07-22 13:59:21 +00:00
|
|
|
struct path path;
|
2005-04-16 22:20:36 +00:00
|
|
|
int error;
|
2012-12-20 22:08:32 +00:00
|
|
|
unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
|
|
|
|
retry:
|
|
|
|
error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
|
2010-07-23 15:43:51 +00:00
|
|
|
error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (error)
|
|
|
|
goto dput_and_out;
|
|
|
|
|
|
|
|
error = -EPERM;
|
2013-03-20 19:49:49 +00:00
|
|
|
if (!ns_capable(current_user_ns(), CAP_SYS_CHROOT))
|
2005-04-16 22:20:36 +00:00
|
|
|
goto dput_and_out;
|
2009-10-04 12:49:48 +00:00
|
|
|
error = security_path_chroot(&path);
|
|
|
|
if (error)
|
|
|
|
goto dput_and_out;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2008-07-22 13:59:21 +00:00
|
|
|
set_fs_root(current->fs, &path);
|
2005-04-16 22:20:36 +00:00
|
|
|
error = 0;
|
|
|
|
dput_and_out:
|
2008-07-22 13:59:21 +00:00
|
|
|
path_put(&path);
|
2012-12-20 22:08:32 +00:00
|
|
|
if (retry_estale(error, lookup_flags)) {
|
|
|
|
lookup_flags |= LOOKUP_REVAL;
|
|
|
|
goto retry;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
out:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2018-03-11 10:34:41 +00:00
|
|
|
SYSCALL_DEFINE1(chroot, const char __user *, filename)
|
|
|
|
{
|
|
|
|
return ksys_chroot(filename);
|
|
|
|
}
|
|
|
|
|
2016-03-25 18:56:23 +00:00
|
|
|
static int chmod_common(const struct path *path, umode_t mode)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2011-07-26 08:15:54 +00:00
|
|
|
struct inode *inode = path->dentry->d_inode;
|
2011-09-20 21:19:26 +00:00
|
|
|
struct inode *delegated_inode = NULL;
|
2005-04-16 22:20:36 +00:00
|
|
|
struct iattr newattrs;
|
2011-07-26 08:15:54 +00:00
|
|
|
int error;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2011-07-26 08:15:54 +00:00
|
|
|
error = mnt_want_write(path->mnt);
|
|
|
|
if (error)
|
|
|
|
return error;
|
2011-09-20 21:19:26 +00:00
|
|
|
retry_deleg:
|
2016-01-22 20:40:57 +00:00
|
|
|
inode_lock(inode);
|
2011-12-08 15:51:53 +00:00
|
|
|
error = security_path_chmod(path, mode);
|
2011-07-26 08:15:54 +00:00
|
|
|
if (error)
|
2009-11-22 02:49:55 +00:00
|
|
|
goto out_unlock;
|
2005-04-16 22:20:36 +00:00
|
|
|
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
|
|
|
|
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
|
2011-09-20 21:19:26 +00:00
|
|
|
error = notify_change(path->dentry, &newattrs, &delegated_inode);
|
2009-11-22 02:49:55 +00:00
|
|
|
out_unlock:
|
2016-01-22 20:40:57 +00:00
|
|
|
inode_unlock(inode);
|
2011-09-20 21:19:26 +00:00
|
|
|
if (delegated_inode) {
|
|
|
|
error = break_deleg_wait(&delegated_inode);
|
|
|
|
if (!error)
|
|
|
|
goto retry_deleg;
|
|
|
|
}
|
2011-07-26 08:15:54 +00:00
|
|
|
mnt_drop_write(path->mnt);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2018-03-11 10:34:53 +00:00
|
|
|
int ksys_fchmod(unsigned int fd, umode_t mode)
|
2011-07-26 08:15:54 +00:00
|
|
|
{
|
2013-08-30 16:48:53 +00:00
|
|
|
struct fd f = fdget(fd);
|
2011-07-26 08:15:54 +00:00
|
|
|
int err = -EBADF;
|
|
|
|
|
2013-08-30 16:48:53 +00:00
|
|
|
if (f.file) {
|
2014-10-31 21:44:57 +00:00
|
|
|
audit_file(f.file);
|
2013-08-30 16:48:53 +00:00
|
|
|
err = chmod_common(&f.file->f_path, mode);
|
|
|
|
fdput(f);
|
2011-07-26 08:15:54 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2018-03-11 10:34:53 +00:00
|
|
|
SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
|
|
|
|
{
|
|
|
|
return ksys_fchmod(fd, mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
int do_fchmodat(int dfd, const char __user *filename, umode_t mode)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2008-07-22 13:59:21 +00:00
|
|
|
struct path path;
|
2005-04-16 22:20:36 +00:00
|
|
|
int error;
|
2012-12-11 17:10:13 +00:00
|
|
|
unsigned int lookup_flags = LOOKUP_FOLLOW;
|
|
|
|
retry:
|
|
|
|
error = user_path_at(dfd, filename, lookup_flags, &path);
|
2011-07-26 08:15:54 +00:00
|
|
|
if (!error) {
|
|
|
|
error = chmod_common(&path, mode);
|
|
|
|
path_put(&path);
|
2012-12-11 17:10:13 +00:00
|
|
|
if (retry_estale(error, lookup_flags)) {
|
|
|
|
lookup_flags |= LOOKUP_REVAL;
|
|
|
|
goto retry;
|
|
|
|
}
|
2011-07-26 08:15:54 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2018-03-11 10:34:53 +00:00
|
|
|
SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename,
|
|
|
|
umode_t, mode)
|
|
|
|
{
|
|
|
|
return do_fchmodat(dfd, filename, mode);
|
|
|
|
}
|
|
|
|
|
2011-07-26 08:22:01 +00:00
|
|
|
SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
|
2006-01-19 01:43:53 +00:00
|
|
|
{
|
2018-03-11 10:34:53 +00:00
|
|
|
return do_fchmodat(AT_FDCWD, filename, mode);
|
2006-01-19 01:43:53 +00:00
|
|
|
}
|
|
|
|
|
2016-03-25 18:44:41 +00:00
|
|
|
static int chown_common(const struct path *path, uid_t user, gid_t group)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2009-11-22 02:49:55 +00:00
|
|
|
struct inode *inode = path->dentry->d_inode;
|
2011-09-20 21:19:26 +00:00
|
|
|
struct inode *delegated_inode = NULL;
|
2005-04-16 22:20:36 +00:00
|
|
|
int error;
|
|
|
|
struct iattr newattrs;
|
2012-03-04 03:52:01 +00:00
|
|
|
kuid_t uid;
|
|
|
|
kgid_t gid;
|
|
|
|
|
|
|
|
uid = make_kuid(current_user_ns(), user);
|
|
|
|
gid = make_kgid(current_user_ns(), group);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2015-02-23 13:51:24 +00:00
|
|
|
retry_deleg:
|
2005-04-16 22:20:36 +00:00
|
|
|
newattrs.ia_valid = ATTR_CTIME;
|
|
|
|
if (user != (uid_t) -1) {
|
2012-03-04 03:52:01 +00:00
|
|
|
if (!uid_valid(uid))
|
|
|
|
return -EINVAL;
|
2005-04-16 22:20:36 +00:00
|
|
|
newattrs.ia_valid |= ATTR_UID;
|
2012-03-04 03:52:01 +00:00
|
|
|
newattrs.ia_uid = uid;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
if (group != (gid_t) -1) {
|
2012-03-04 03:52:01 +00:00
|
|
|
if (!gid_valid(gid))
|
|
|
|
return -EINVAL;
|
2005-04-16 22:20:36 +00:00
|
|
|
newattrs.ia_valid |= ATTR_GID;
|
2012-03-04 03:52:01 +00:00
|
|
|
newattrs.ia_gid = gid;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
if (!S_ISDIR(inode->i_mode))
|
Implement file posix capabilities
Implement file posix capabilities. This allows programs to be given a
subset of root's powers regardless of who runs them, without having to use
setuid and giving the binary all of root's powers.
This version works with Kaigai Kohei's userspace tools, found at
http://www.kaigai.gr.jp/index.php. For more information on how to use this
patch, Chris Friedhoff has posted a nice page at
http://www.friedhoff.org/fscaps.html.
Changelog:
Nov 27:
Incorporate fixes from Andrew Morton
(security-introduce-file-caps-tweaks and
security-introduce-file-caps-warning-fix)
Fix Kconfig dependency.
Fix change signaling behavior when file caps are not compiled in.
Nov 13:
Integrate comments from Alexey: Remove CONFIG_ ifdef from
capability.h, and use %zd for printing a size_t.
Nov 13:
Fix endianness warnings by sparse as suggested by Alexey
Dobriyan.
Nov 09:
Address warnings of unused variables at cap_bprm_set_security
when file capabilities are disabled, and simultaneously clean
up the code a little, by pulling the new code into a helper
function.
Nov 08:
For pointers to required userspace tools and how to use
them, see http://www.friedhoff.org/fscaps.html.
Nov 07:
Fix the calculation of the highest bit checked in
check_cap_sanity().
Nov 07:
Allow file caps to be enabled without CONFIG_SECURITY, since
capabilities are the default.
Hook cap_task_setscheduler when !CONFIG_SECURITY.
Move capable(TASK_KILL) to end of cap_task_kill to reduce
audit messages.
Nov 05:
Add secondary calls in selinux/hooks.c to task_setioprio and
task_setscheduler so that selinux and capabilities with file
cap support can be stacked.
Sep 05:
As Seth Arnold points out, uid checks are out of place
for capability code.
Sep 01:
Define task_setscheduler, task_setioprio, cap_task_kill, and
task_setnice to make sure a user cannot affect a process in which
they called a program with some fscaps.
One remaining question is the note under task_setscheduler: are we
ok with CAP_SYS_NICE being sufficient to confine a process to a
cpuset?
It is a semantic change, as without fsccaps, attach_task doesn't
allow CAP_SYS_NICE to override the uid equivalence check. But since
it uses security_task_setscheduler, which elsewhere is used where
CAP_SYS_NICE can be used to override the uid equivalence check,
fixing it might be tough.
task_setscheduler
note: this also controls cpuset:attach_task. Are we ok with
CAP_SYS_NICE being used to confine to a cpuset?
task_setioprio
task_setnice
sys_setpriority uses this (through set_one_prio) for another
process. Need same checks as setrlimit
Aug 21:
Updated secureexec implementation to reflect the fact that
euid and uid might be the same and nonzero, but the process
might still have elevated caps.
Aug 15:
Handle endianness of xattrs.
Enforce capability version match between kernel and disk.
Enforce that no bits beyond the known max capability are
set, else return -EPERM.
With this extra processing, it may be worth reconsidering
doing all the work at bprm_set_security rather than
d_instantiate.
Aug 10:
Always call getxattr at bprm_set_security, rather than
caching it at d_instantiate.
[morgan@kernel.org: file-caps clean up for linux/capability.h]
[bunk@kernel.org: unexport cap_inode_killpriv]
Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Cc: James Morris <jmorris@namei.org>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: Andrew Morgan <morgan@kernel.org>
Signed-off-by: Andrew Morgan <morgan@kernel.org>
Signed-off-by: Adrian Bunk <bunk@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-10-17 06:31:36 +00:00
|
|
|
newattrs.ia_valid |=
|
|
|
|
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
|
2016-01-22 20:40:57 +00:00
|
|
|
inode_lock(inode);
|
2012-06-01 22:14:19 +00:00
|
|
|
error = security_path_chown(path, uid, gid);
|
2009-11-22 02:49:55 +00:00
|
|
|
if (!error)
|
2011-09-20 21:19:26 +00:00
|
|
|
error = notify_change(path->dentry, &newattrs, &delegated_inode);
|
2016-01-22 20:40:57 +00:00
|
|
|
inode_unlock(inode);
|
2011-09-20 21:19:26 +00:00
|
|
|
if (delegated_inode) {
|
|
|
|
error = break_deleg_wait(&delegated_inode);
|
|
|
|
if (!error)
|
|
|
|
goto retry_deleg;
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
fs: add do_fchownat(), ksys_fchown() helpers and ksys_{,l}chown() wrappers
Using the fs-interal do_fchownat() wrapper allows us to get rid of
fs-internal calls to the sys_fchownat() syscall.
Introducing the ksys_fchown() helper and the ksys_{,}chown() wrappers
allows us to avoid the in-kernel calls to the sys_{,l,f}chown() syscalls.
The ksys_ prefix denotes that these functions are meant as a drop-in
replacement for the syscalls. In particular, they use the same calling
convention as sys_{,l,f}chown().
This patch is part of a series which removes in-kernel calls to syscalls.
On this basis, the syscall entry path can be streamlined. For details, see
http://lkml.kernel.org/r/20180325162527.GA17492@light.dominikbrodowski.net
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
2018-03-11 10:34:55 +00:00
|
|
|
int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
|
|
|
|
int flag)
|
2006-01-19 01:43:53 +00:00
|
|
|
{
|
2008-07-22 13:59:21 +00:00
|
|
|
struct path path;
|
2006-01-19 01:43:53 +00:00
|
|
|
int error = -EINVAL;
|
2011-03-13 19:56:26 +00:00
|
|
|
int lookup_flags;
|
2006-01-19 01:43:53 +00:00
|
|
|
|
2011-03-13 19:56:26 +00:00
|
|
|
if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
|
2006-01-19 01:43:53 +00:00
|
|
|
goto out;
|
|
|
|
|
2011-03-13 19:56:26 +00:00
|
|
|
lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
|
|
|
|
if (flag & AT_EMPTY_PATH)
|
|
|
|
lookup_flags |= LOOKUP_EMPTY;
|
2012-12-11 17:10:13 +00:00
|
|
|
retry:
|
2011-03-13 19:56:26 +00:00
|
|
|
error = user_path_at(dfd, filename, lookup_flags, &path);
|
2006-10-01 06:29:01 +00:00
|
|
|
if (error)
|
|
|
|
goto out;
|
2008-07-22 13:59:21 +00:00
|
|
|
error = mnt_want_write(path.mnt);
|
2008-02-15 22:37:50 +00:00
|
|
|
if (error)
|
|
|
|
goto out_release;
|
2009-11-22 02:49:55 +00:00
|
|
|
error = chown_common(&path, user, group);
|
2008-07-22 13:59:21 +00:00
|
|
|
mnt_drop_write(path.mnt);
|
2008-02-15 22:37:50 +00:00
|
|
|
out_release:
|
2008-07-22 13:59:21 +00:00
|
|
|
path_put(&path);
|
2012-12-11 17:10:13 +00:00
|
|
|
if (retry_estale(error, lookup_flags)) {
|
|
|
|
lookup_flags |= LOOKUP_REVAL;
|
|
|
|
goto retry;
|
|
|
|
}
|
2006-01-19 01:43:53 +00:00
|
|
|
out:
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
fs: add do_fchownat(), ksys_fchown() helpers and ksys_{,l}chown() wrappers
Using the fs-interal do_fchownat() wrapper allows us to get rid of
fs-internal calls to the sys_fchownat() syscall.
Introducing the ksys_fchown() helper and the ksys_{,}chown() wrappers
allows us to avoid the in-kernel calls to the sys_{,l,f}chown() syscalls.
The ksys_ prefix denotes that these functions are meant as a drop-in
replacement for the syscalls. In particular, they use the same calling
convention as sys_{,l,f}chown().
This patch is part of a series which removes in-kernel calls to syscalls.
On this basis, the syscall entry path can be streamlined. For details, see
http://lkml.kernel.org/r/20180325162527.GA17492@light.dominikbrodowski.net
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
2018-03-11 10:34:55 +00:00
|
|
|
SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
|
|
|
|
gid_t, group, int, flag)
|
|
|
|
{
|
|
|
|
return do_fchownat(dfd, filename, user, group, flag);
|
|
|
|
}
|
|
|
|
|
2012-06-25 11:55:09 +00:00
|
|
|
SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
fs: add do_fchownat(), ksys_fchown() helpers and ksys_{,l}chown() wrappers
Using the fs-interal do_fchownat() wrapper allows us to get rid of
fs-internal calls to the sys_fchownat() syscall.
Introducing the ksys_fchown() helper and the ksys_{,}chown() wrappers
allows us to avoid the in-kernel calls to the sys_{,l,f}chown() syscalls.
The ksys_ prefix denotes that these functions are meant as a drop-in
replacement for the syscalls. In particular, they use the same calling
convention as sys_{,l,f}chown().
This patch is part of a series which removes in-kernel calls to syscalls.
On this basis, the syscall entry path can be streamlined. For details, see
http://lkml.kernel.org/r/20180325162527.GA17492@light.dominikbrodowski.net
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
2018-03-11 10:34:55 +00:00
|
|
|
return do_fchownat(AT_FDCWD, filename, user, group, 0);
|
2012-06-25 11:55:09 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2012-06-25 11:55:09 +00:00
|
|
|
SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
|
|
|
|
{
|
fs: add do_fchownat(), ksys_fchown() helpers and ksys_{,l}chown() wrappers
Using the fs-interal do_fchownat() wrapper allows us to get rid of
fs-internal calls to the sys_fchownat() syscall.
Introducing the ksys_fchown() helper and the ksys_{,}chown() wrappers
allows us to avoid the in-kernel calls to the sys_{,l,f}chown() syscalls.
The ksys_ prefix denotes that these functions are meant as a drop-in
replacement for the syscalls. In particular, they use the same calling
convention as sys_{,l,f}chown().
This patch is part of a series which removes in-kernel calls to syscalls.
On this basis, the syscall entry path can be streamlined. For details, see
http://lkml.kernel.org/r/20180325162527.GA17492@light.dominikbrodowski.net
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
2018-03-11 10:34:55 +00:00
|
|
|
return do_fchownat(AT_FDCWD, filename, user, group,
|
|
|
|
AT_SYMLINK_NOFOLLOW);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
fs: add do_fchownat(), ksys_fchown() helpers and ksys_{,l}chown() wrappers
Using the fs-interal do_fchownat() wrapper allows us to get rid of
fs-internal calls to the sys_fchownat() syscall.
Introducing the ksys_fchown() helper and the ksys_{,}chown() wrappers
allows us to avoid the in-kernel calls to the sys_{,l,f}chown() syscalls.
The ksys_ prefix denotes that these functions are meant as a drop-in
replacement for the syscalls. In particular, they use the same calling
convention as sys_{,l,f}chown().
This patch is part of a series which removes in-kernel calls to syscalls.
On this basis, the syscall entry path can be streamlined. For details, see
http://lkml.kernel.org/r/20180325162527.GA17492@light.dominikbrodowski.net
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
2018-03-11 10:34:55 +00:00
|
|
|
int ksys_fchown(unsigned int fd, uid_t user, gid_t group)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-08-28 16:52:22 +00:00
|
|
|
struct fd f = fdget(fd);
|
2005-04-16 22:20:36 +00:00
|
|
|
int error = -EBADF;
|
|
|
|
|
2012-08-28 16:52:22 +00:00
|
|
|
if (!f.file)
|
2006-10-01 06:29:01 +00:00
|
|
|
goto out;
|
|
|
|
|
2018-07-18 13:44:43 +00:00
|
|
|
error = mnt_want_write_file(f.file);
|
2008-02-15 22:37:50 +00:00
|
|
|
if (error)
|
|
|
|
goto out_fput;
|
2014-10-31 21:44:57 +00:00
|
|
|
audit_file(f.file);
|
2012-08-28 16:52:22 +00:00
|
|
|
error = chown_common(&f.file->f_path, user, group);
|
2018-07-18 13:44:43 +00:00
|
|
|
mnt_drop_write_file(f.file);
|
2008-02-15 22:37:50 +00:00
|
|
|
out_fput:
|
2012-08-28 16:52:22 +00:00
|
|
|
fdput(f);
|
2006-10-01 06:29:01 +00:00
|
|
|
out:
|
2005-04-16 22:20:36 +00:00
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
fs: add do_fchownat(), ksys_fchown() helpers and ksys_{,l}chown() wrappers
Using the fs-interal do_fchownat() wrapper allows us to get rid of
fs-internal calls to the sys_fchownat() syscall.
Introducing the ksys_fchown() helper and the ksys_{,}chown() wrappers
allows us to avoid the in-kernel calls to the sys_{,l,f}chown() syscalls.
The ksys_ prefix denotes that these functions are meant as a drop-in
replacement for the syscalls. In particular, they use the same calling
convention as sys_{,l,f}chown().
This patch is part of a series which removes in-kernel calls to syscalls.
On this basis, the syscall entry path can be streamlined. For details, see
http://lkml.kernel.org/r/20180325162527.GA17492@light.dominikbrodowski.net
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
2018-03-11 10:34:55 +00:00
|
|
|
SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
|
|
|
|
{
|
|
|
|
return ksys_fchown(fd, user, group);
|
|
|
|
}
|
|
|
|
|
2012-06-10 18:32:45 +00:00
|
|
|
static int do_dentry_open(struct file *f,
|
2015-06-18 13:32:31 +00:00
|
|
|
struct inode *inode,
|
2018-07-10 17:22:28 +00:00
|
|
|
int (*open)(struct inode *, struct file *))
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
New kind of open files - "location only".
New flag for open(2) - O_PATH. Semantics:
* pathname is resolved, but the file itself is _NOT_ opened
as far as filesystem is concerned.
* almost all operations on the resulting descriptors shall
fail with -EBADF. Exceptions are:
1) operations on descriptors themselves (i.e.
close(), dup(), dup2(), dup3(), fcntl(fd, F_DUPFD),
fcntl(fd, F_DUPFD_CLOEXEC, ...), fcntl(fd, F_GETFD),
fcntl(fd, F_SETFD, ...))
2) fcntl(fd, F_GETFL), for a common non-destructive way to
check if descriptor is open
3) "dfd" arguments of ...at(2) syscalls, i.e. the starting
points of pathname resolution
* closing such descriptor does *NOT* affect dnotify or
posix locks.
* permissions are checked as usual along the way to file;
no permission checks are applied to the file itself. Of course,
giving such thing to syscall will result in permission checks (at
the moment it means checking that starting point of ....at() is
a directory and caller has exec permissions on it).
fget() and fget_light() return NULL on such descriptors; use of
fget_raw() and fget_raw_light() is needed to get them. That protects
existing code from dealing with those things.
There are two things still missing (they come in the next commits):
one is handling of symlinks (right now we refuse to open them that
way; see the next commit for semantics related to those) and another
is descriptor passing via SCM_RIGHTS datagrams.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2011-03-13 07:51:11 +00:00
|
|
|
static const struct file_operations empty_fops = {};
|
2005-04-16 22:20:36 +00:00
|
|
|
int error;
|
|
|
|
|
2012-07-20 19:28:46 +00:00
|
|
|
path_get(&f->f_path);
|
2015-06-18 13:32:31 +00:00
|
|
|
f->f_inode = inode;
|
2005-04-16 22:20:36 +00:00
|
|
|
f->f_mapping = inode->i_mapping;
|
|
|
|
|
fs: new infrastructure for writeback error handling and reporting
Most filesystems currently use mapping_set_error and
filemap_check_errors for setting and reporting/clearing writeback errors
at the mapping level. filemap_check_errors is indirectly called from
most of the filemap_fdatawait_* functions and from
filemap_write_and_wait*. These functions are called from all sorts of
contexts to wait on writeback to finish -- e.g. mostly in fsync, but
also in truncate calls, getattr, etc.
The non-fsync callers are problematic. We should be reporting writeback
errors during fsync, but many places spread over the tree clear out
errors before they can be properly reported, or report errors at
nonsensical times.
If I get -EIO on a stat() call, there is no reason for me to assume that
it is because some previous writeback failed. The fact that it also
clears out the error such that a subsequent fsync returns 0 is a bug,
and a nasty one since that's potentially silent data corruption.
This patch adds a small bit of new infrastructure for setting and
reporting errors during address_space writeback. While the above was my
original impetus for adding this, I think it's also the case that
current fsync semantics are just problematic for userland. Most
applications that call fsync do so to ensure that the data they wrote
has hit the backing store.
In the case where there are multiple writers to the file at the same
time, this is really hard to determine. The first one to call fsync will
see any stored error, and the rest get back 0. The processes with open
fds may not be associated with one another in any way. They could even
be in different containers, so ensuring coordination between all fsync
callers is not really an option.
One way to remedy this would be to track what file descriptor was used
to dirty the file, but that's rather cumbersome and would likely be
slow. However, there is a simpler way to improve the semantics here
without incurring too much overhead.
This set adds an errseq_t to struct address_space, and a corresponding
one is added to struct file. Writeback errors are recorded in the
mapping's errseq_t, and the one in struct file is used as the "since"
value.
This changes the semantics of the Linux fsync implementation such that
applications can now use it to determine whether there were any
writeback errors since fsync(fd) was last called (or since the file was
opened in the case of fsync having never been called).
Note that those writeback errors may have occurred when writing data
that was dirtied via an entirely different fd, but that's the case now
with the current mapping_set_error/filemap_check_error infrastructure.
This will at least prevent you from getting a false report of success.
The new behavior is still consistent with the POSIX spec, and is more
reliable for application developers. This patch just adds some basic
infrastructure for doing this, and ensures that the f_wb_err "cursor"
is properly set when a file is opened. Later patches will change the
existing code to use this new infrastructure for reporting errors at
fsync time.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Reviewed-by: Jan Kara <jack@suse.cz>
2017-07-06 11:02:25 +00:00
|
|
|
/* Ensure that we skip any errors that predate opening of the file */
|
|
|
|
f->f_wb_err = filemap_sample_wb_err(f->f_mapping);
|
|
|
|
|
2014-03-14 13:43:29 +00:00
|
|
|
if (unlikely(f->f_flags & O_PATH)) {
|
2018-07-09 06:35:08 +00:00
|
|
|
f->f_mode = FMODE_PATH | FMODE_OPENED;
|
New kind of open files - "location only".
New flag for open(2) - O_PATH. Semantics:
* pathname is resolved, but the file itself is _NOT_ opened
as far as filesystem is concerned.
* almost all operations on the resulting descriptors shall
fail with -EBADF. Exceptions are:
1) operations on descriptors themselves (i.e.
close(), dup(), dup2(), dup3(), fcntl(fd, F_DUPFD),
fcntl(fd, F_DUPFD_CLOEXEC, ...), fcntl(fd, F_GETFD),
fcntl(fd, F_SETFD, ...))
2) fcntl(fd, F_GETFL), for a common non-destructive way to
check if descriptor is open
3) "dfd" arguments of ...at(2) syscalls, i.e. the starting
points of pathname resolution
* closing such descriptor does *NOT* affect dnotify or
posix locks.
* permissions are checked as usual along the way to file;
no permission checks are applied to the file itself. Of course,
giving such thing to syscall will result in permission checks (at
the moment it means checking that starting point of ....at() is
a directory and caller has exec permissions on it).
fget() and fget_light() return NULL on such descriptors; use of
fget_raw() and fget_raw_light() is needed to get them. That protects
existing code from dealing with those things.
There are two things still missing (they come in the next commits):
one is handling of symlinks (right now we refuse to open them that
way; see the next commit for semantics related to those) and another
is descriptor passing via SCM_RIGHTS datagrams.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2011-03-13 07:51:11 +00:00
|
|
|
f->f_op = &empty_fops;
|
Revert "fs: fold open_check_o_direct into do_dentry_open"
This reverts commit cab64df194667dc5d9d786f0a895f647f5501c0d.
Having vfs_open() in some cases drop the reference to
struct file combined with
error = vfs_open(path, f, cred);
if (error) {
put_filp(f);
return ERR_PTR(error);
}
return f;
is flat-out wrong. It used to be
error = vfs_open(path, f, cred);
if (!error) {
/* from now on we need fput() to dispose of f */
error = open_check_o_direct(f);
if (error) {
fput(f);
f = ERR_PTR(error);
}
} else {
put_filp(f);
f = ERR_PTR(error);
}
and sure, having that open_check_o_direct() boilerplate gotten rid of is
nice, but not that way...
Worse, another call chain (via finish_open()) is FUBAR now wrt
FILE_OPENED handling - in that case we get error returned, with file
already hit by fput() *AND* FILE_OPENED not set. Guess what happens in
path_openat(), when it hits
if (!(opened & FILE_OPENED)) {
BUG_ON(!error);
put_filp(file);
}
The root cause of all that crap is that the callers of do_dentry_open()
have no way to tell which way did it fail; while that could be fixed up
(by passing something like int *opened to do_dentry_open() and have it
marked if we'd called ->open()), it's probably much too late in the
cycle to do so right now.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-06-02 05:31:02 +00:00
|
|
|
return 0;
|
New kind of open files - "location only".
New flag for open(2) - O_PATH. Semantics:
* pathname is resolved, but the file itself is _NOT_ opened
as far as filesystem is concerned.
* almost all operations on the resulting descriptors shall
fail with -EBADF. Exceptions are:
1) operations on descriptors themselves (i.e.
close(), dup(), dup2(), dup3(), fcntl(fd, F_DUPFD),
fcntl(fd, F_DUPFD_CLOEXEC, ...), fcntl(fd, F_GETFD),
fcntl(fd, F_SETFD, ...))
2) fcntl(fd, F_GETFL), for a common non-destructive way to
check if descriptor is open
3) "dfd" arguments of ...at(2) syscalls, i.e. the starting
points of pathname resolution
* closing such descriptor does *NOT* affect dnotify or
posix locks.
* permissions are checked as usual along the way to file;
no permission checks are applied to the file itself. Of course,
giving such thing to syscall will result in permission checks (at
the moment it means checking that starting point of ....at() is
a directory and caller has exec permissions on it).
fget() and fget_light() return NULL on such descriptors; use of
fget_raw() and fget_raw_light() is needed to get them. That protects
existing code from dealing with those things.
There are two things still missing (they come in the next commits):
one is handling of symlinks (right now we refuse to open them that
way; see the next commit for semantics related to those) and another
is descriptor passing via SCM_RIGHTS datagrams.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2011-03-13 07:51:11 +00:00
|
|
|
}
|
|
|
|
|
2019-03-29 03:43:30 +00:00
|
|
|
/* Any file opened for execve()/uselib() has to be a regular file. */
|
|
|
|
if (unlikely(f->f_flags & FMODE_EXEC && !S_ISREG(inode->i_mode))) {
|
|
|
|
error = -EACCES;
|
|
|
|
goto cleanup_file;
|
|
|
|
}
|
|
|
|
|
2014-03-14 14:56:20 +00:00
|
|
|
if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) {
|
2014-03-14 14:40:46 +00:00
|
|
|
error = get_write_access(inode);
|
2014-03-14 13:43:29 +00:00
|
|
|
if (unlikely(error))
|
2005-04-16 22:20:36 +00:00
|
|
|
goto cleanup_file;
|
2014-03-14 14:40:46 +00:00
|
|
|
error = __mnt_want_write(f->f_path.mnt);
|
2014-03-14 13:43:29 +00:00
|
|
|
if (unlikely(error)) {
|
2014-03-14 14:40:46 +00:00
|
|
|
put_write_access(inode);
|
|
|
|
goto cleanup_file;
|
|
|
|
}
|
2014-03-14 16:02:47 +00:00
|
|
|
f->f_mode |= FMODE_WRITER;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2014-03-03 17:36:58 +00:00
|
|
|
/* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */
|
2016-04-20 21:08:21 +00:00
|
|
|
if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))
|
2014-03-03 17:36:58 +00:00
|
|
|
f->f_mode |= FMODE_ATOMIC_POS;
|
|
|
|
|
New kind of open files - "location only".
New flag for open(2) - O_PATH. Semantics:
* pathname is resolved, but the file itself is _NOT_ opened
as far as filesystem is concerned.
* almost all operations on the resulting descriptors shall
fail with -EBADF. Exceptions are:
1) operations on descriptors themselves (i.e.
close(), dup(), dup2(), dup3(), fcntl(fd, F_DUPFD),
fcntl(fd, F_DUPFD_CLOEXEC, ...), fcntl(fd, F_GETFD),
fcntl(fd, F_SETFD, ...))
2) fcntl(fd, F_GETFL), for a common non-destructive way to
check if descriptor is open
3) "dfd" arguments of ...at(2) syscalls, i.e. the starting
points of pathname resolution
* closing such descriptor does *NOT* affect dnotify or
posix locks.
* permissions are checked as usual along the way to file;
no permission checks are applied to the file itself. Of course,
giving such thing to syscall will result in permission checks (at
the moment it means checking that starting point of ....at() is
a directory and caller has exec permissions on it).
fget() and fget_light() return NULL on such descriptors; use of
fget_raw() and fget_raw_light() is needed to get them. That protects
existing code from dealing with those things.
There are two things still missing (they come in the next commits):
one is handling of symlinks (right now we refuse to open them that
way; see the next commit for semantics related to those) and another
is descriptor passing via SCM_RIGHTS datagrams.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2011-03-13 07:51:11 +00:00
|
|
|
f->f_op = fops_get(inode->i_fop);
|
2013-09-22 20:27:52 +00:00
|
|
|
if (unlikely(WARN_ON(!f->f_op))) {
|
|
|
|
error = -ENODEV;
|
|
|
|
goto cleanup_all;
|
|
|
|
}
|
New kind of open files - "location only".
New flag for open(2) - O_PATH. Semantics:
* pathname is resolved, but the file itself is _NOT_ opened
as far as filesystem is concerned.
* almost all operations on the resulting descriptors shall
fail with -EBADF. Exceptions are:
1) operations on descriptors themselves (i.e.
close(), dup(), dup2(), dup3(), fcntl(fd, F_DUPFD),
fcntl(fd, F_DUPFD_CLOEXEC, ...), fcntl(fd, F_GETFD),
fcntl(fd, F_SETFD, ...))
2) fcntl(fd, F_GETFL), for a common non-destructive way to
check if descriptor is open
3) "dfd" arguments of ...at(2) syscalls, i.e. the starting
points of pathname resolution
* closing such descriptor does *NOT* affect dnotify or
posix locks.
* permissions are checked as usual along the way to file;
no permission checks are applied to the file itself. Of course,
giving such thing to syscall will result in permission checks (at
the moment it means checking that starting point of ....at() is
a directory and caller has exec permissions on it).
fget() and fget_light() return NULL on such descriptors; use of
fget_raw() and fget_raw_light() is needed to get them. That protects
existing code from dealing with those things.
There are two things still missing (they come in the next commits):
one is handling of symlinks (right now we refuse to open them that
way; see the next commit for semantics related to those) and another
is descriptor passing via SCM_RIGHTS datagrams.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2011-03-13 07:51:11 +00:00
|
|
|
|
2018-07-10 17:25:29 +00:00
|
|
|
error = security_file_open(f);
|
2007-09-14 00:27:07 +00:00
|
|
|
if (error)
|
|
|
|
goto cleanup_all;
|
|
|
|
|
2016-09-16 10:44:20 +00:00
|
|
|
error = break_lease(locks_inode(f), f->f_flags);
|
2011-09-21 14:58:13 +00:00
|
|
|
if (error)
|
|
|
|
goto cleanup_all;
|
|
|
|
|
2018-07-11 19:00:04 +00:00
|
|
|
/* normally all 3 are set; ->open() can clear them if needed */
|
|
|
|
f->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
|
2013-09-22 20:27:52 +00:00
|
|
|
if (!open)
|
2005-10-18 21:20:16 +00:00
|
|
|
open = f->f_op->open;
|
|
|
|
if (open) {
|
|
|
|
error = open(inode, f);
|
2005-04-16 22:20:36 +00:00
|
|
|
if (error)
|
|
|
|
goto cleanup_all;
|
|
|
|
}
|
2018-07-09 06:35:08 +00:00
|
|
|
f->f_mode |= FMODE_OPENED;
|
2010-11-02 14:13:07 +00:00
|
|
|
if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
|
|
|
|
i_readcount_inc(inode);
|
2014-02-11 23:37:41 +00:00
|
|
|
if ((f->f_mode & FMODE_READ) &&
|
2015-04-04 05:14:53 +00:00
|
|
|
likely(f->f_op->read || f->f_op->read_iter))
|
2014-02-11 22:49:24 +00:00
|
|
|
f->f_mode |= FMODE_CAN_READ;
|
2014-02-11 23:37:41 +00:00
|
|
|
if ((f->f_mode & FMODE_WRITE) &&
|
2015-04-04 05:14:53 +00:00
|
|
|
likely(f->f_op->write || f->f_op->write_iter))
|
2014-02-11 22:49:24 +00:00
|
|
|
f->f_mode |= FMODE_CAN_WRITE;
|
2005-10-18 21:20:16 +00:00
|
|
|
|
fs: add fcntl() interface for setting/getting write life time hints
Define a set of write life time hints:
RWH_WRITE_LIFE_NOT_SET No hint information set
RWH_WRITE_LIFE_NONE No hints about write life time
RWH_WRITE_LIFE_SHORT Data written has a short life time
RWH_WRITE_LIFE_MEDIUM Data written has a medium life time
RWH_WRITE_LIFE_LONG Data written has a long life time
RWH_WRITE_LIFE_EXTREME Data written has an extremely long life time
The intent is for these values to be relative to each other, no
absolute meaning should be attached to these flag names.
Add an fcntl interface for querying these flags, and also for
setting them as well:
F_GET_RW_HINT Returns the read/write hint set on the
underlying inode.
F_SET_RW_HINT Set one of the above write hints on the
underlying inode.
F_GET_FILE_RW_HINT Returns the read/write hint set on the
file descriptor.
F_SET_FILE_RW_HINT Set one of the above write hints on the
file descriptor.
The user passes in a 64-bit pointer to get/set these values, and
the interface returns 0/-1 on success/error.
Sample program testing/implementing basic setting/getting of write
hints is below.
Add support for storing the write life time hint in the inode flags
and in struct file as well, and pass them to the kiocb flags. If
both a file and its corresponding inode has a write hint, then we
use the one in the file, if available. The file hint can be used
for sync/direct IO, for buffered writeback only the inode hint
is available.
This is in preparation for utilizing these hints in the block layer,
to guide on-media data placement.
/*
* writehint.c: get or set an inode write hint
*/
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <inttypes.h>
#ifndef F_GET_RW_HINT
#define F_LINUX_SPECIFIC_BASE 1024
#define F_GET_RW_HINT (F_LINUX_SPECIFIC_BASE + 11)
#define F_SET_RW_HINT (F_LINUX_SPECIFIC_BASE + 12)
#endif
static char *str[] = { "RWF_WRITE_LIFE_NOT_SET", "RWH_WRITE_LIFE_NONE",
"RWH_WRITE_LIFE_SHORT", "RWH_WRITE_LIFE_MEDIUM",
"RWH_WRITE_LIFE_LONG", "RWH_WRITE_LIFE_EXTREME" };
int main(int argc, char *argv[])
{
uint64_t hint;
int fd, ret;
if (argc < 2) {
fprintf(stderr, "%s: file <hint>\n", argv[0]);
return 1;
}
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror("open");
return 2;
}
if (argc > 2) {
hint = atoi(argv[2]);
ret = fcntl(fd, F_SET_RW_HINT, &hint);
if (ret < 0) {
perror("fcntl: F_SET_RW_HINT");
return 4;
}
}
ret = fcntl(fd, F_GET_RW_HINT, &hint);
if (ret < 0) {
perror("fcntl: F_GET_RW_HINT");
return 3;
}
printf("%s: hint %s\n", argv[1], str[hint]);
close(fd);
return 0;
}
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
2017-06-27 17:47:04 +00:00
|
|
|
f->f_write_hint = WRITE_LIFE_NOT_SET;
|
2005-04-16 22:20:36 +00:00
|
|
|
f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
|
|
|
|
|
|
|
|
file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
|
Revert "fs: fold open_check_o_direct into do_dentry_open"
This reverts commit cab64df194667dc5d9d786f0a895f647f5501c0d.
Having vfs_open() in some cases drop the reference to
struct file combined with
error = vfs_open(path, f, cred);
if (error) {
put_filp(f);
return ERR_PTR(error);
}
return f;
is flat-out wrong. It used to be
error = vfs_open(path, f, cred);
if (!error) {
/* from now on we need fput() to dispose of f */
error = open_check_o_direct(f);
if (error) {
fput(f);
f = ERR_PTR(error);
}
} else {
put_filp(f);
f = ERR_PTR(error);
}
and sure, having that open_check_o_direct() boilerplate gotten rid of is
nice, but not that way...
Worse, another call chain (via finish_open()) is FUBAR now wrt
FILE_OPENED handling - in that case we get error returned, with file
already hit by fput() *AND* FILE_OPENED not set. Guess what happens in
path_openat(), when it hits
if (!(opened & FILE_OPENED)) {
BUG_ON(!error);
put_filp(file);
}
The root cause of all that crap is that the callers of do_dentry_open()
have no way to tell which way did it fail; while that could be fixed up
(by passing something like int *opened to do_dentry_open() and have it
marked if we'd called ->open()), it's probably much too late in the
cycle to do so right now.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-06-02 05:31:02 +00:00
|
|
|
|
2018-06-08 17:01:49 +00:00
|
|
|
/* NB: we're sure to have correct a_ops only after f_op->open */
|
|
|
|
if (f->f_flags & O_DIRECT) {
|
|
|
|
if (!f->f_mapping->a_ops || !f->f_mapping->a_ops->direct_IO)
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2019-09-23 22:38:03 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX: Huge page cache doesn't support writing yet. Drop all page
|
|
|
|
* cache for this file before processing writes.
|
|
|
|
*/
|
|
|
|
if ((f->f_mode & FMODE_WRITE) && filemap_nr_thps(inode->i_mapping))
|
|
|
|
truncate_pagecache(inode, 0);
|
|
|
|
|
2012-06-10 18:22:04 +00:00
|
|
|
return 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
cleanup_all:
|
2018-07-09 01:45:07 +00:00
|
|
|
if (WARN_ON_ONCE(error > 0))
|
|
|
|
error = -EINVAL;
|
2005-04-16 22:20:36 +00:00
|
|
|
fops_put(f->f_op);
|
2014-03-14 16:02:47 +00:00
|
|
|
if (f->f_mode & FMODE_WRITER) {
|
2005-04-16 22:20:36 +00:00
|
|
|
put_write_access(inode);
|
2014-03-14 16:02:47 +00:00
|
|
|
__mnt_drop_write(f->f_path.mnt);
|
2008-02-15 22:37:48 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
cleanup_file:
|
2012-06-10 18:32:45 +00:00
|
|
|
path_put(&f->f_path);
|
|
|
|
f->f_path.mnt = NULL;
|
|
|
|
f->f_path.dentry = NULL;
|
2013-03-02 00:48:30 +00:00
|
|
|
f->f_inode = NULL;
|
2012-06-10 18:22:04 +00:00
|
|
|
return error;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2012-06-05 13:10:17 +00:00
|
|
|
/**
|
|
|
|
* finish_open - finish opening a file
|
2013-09-16 12:51:55 +00:00
|
|
|
* @file: file pointer
|
2012-06-05 13:10:17 +00:00
|
|
|
* @dentry: pointer to dentry
|
|
|
|
* @open: open callback
|
2013-09-16 12:51:55 +00:00
|
|
|
* @opened: state of open
|
2012-06-05 13:10:17 +00:00
|
|
|
*
|
|
|
|
* This can be used to finish opening a file passed to i_op->atomic_open().
|
|
|
|
*
|
|
|
|
* If the open callback is set to NULL, then the standard f_op->open()
|
|
|
|
* filesystem callback is substituted.
|
2013-09-16 12:51:55 +00:00
|
|
|
*
|
|
|
|
* NB: the dentry reference is _not_ consumed. If, for example, the dentry is
|
|
|
|
* the return value of d_splice_alias(), then the caller needs to perform dput()
|
|
|
|
* on it after finish_open().
|
|
|
|
*
|
|
|
|
* On successful return @file is a fully instantiated open file. After this, if
|
|
|
|
* an error occurs in ->atomic_open(), it needs to clean up with fput().
|
|
|
|
*
|
|
|
|
* Returns zero on success or -errno if the open failed.
|
2012-06-05 13:10:17 +00:00
|
|
|
*/
|
2012-06-22 08:40:19 +00:00
|
|
|
int finish_open(struct file *file, struct dentry *dentry,
|
2018-06-08 15:44:56 +00:00
|
|
|
int (*open)(struct inode *, struct file *))
|
2012-06-05 13:10:17 +00:00
|
|
|
{
|
2018-06-08 16:58:04 +00:00
|
|
|
BUG_ON(file->f_mode & FMODE_OPENED); /* once it's opened, it's opened */
|
2012-06-05 13:10:17 +00:00
|
|
|
|
2012-07-20 19:28:46 +00:00
|
|
|
file->f_path.dentry = dentry;
|
2018-06-08 16:58:04 +00:00
|
|
|
return do_dentry_open(file, d_backing_inode(dentry), open);
|
2012-06-05 13:10:17 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(finish_open);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* finish_no_open - finish ->atomic_open() without opening the file
|
|
|
|
*
|
2013-09-16 12:51:55 +00:00
|
|
|
* @file: file pointer
|
2012-06-05 13:10:17 +00:00
|
|
|
* @dentry: dentry or NULL (as returned from ->lookup())
|
|
|
|
*
|
|
|
|
* This can be used to set the result of a successful lookup in ->atomic_open().
|
2013-09-16 12:51:55 +00:00
|
|
|
*
|
|
|
|
* NB: unlike finish_open() this function does consume the dentry reference and
|
|
|
|
* the caller need not dput() it.
|
|
|
|
*
|
2018-07-09 23:17:52 +00:00
|
|
|
* Returns "0" which must be the return value of ->atomic_open() after having
|
2013-09-16 12:51:55 +00:00
|
|
|
* called this function.
|
2012-06-05 13:10:17 +00:00
|
|
|
*/
|
2012-06-10 10:48:09 +00:00
|
|
|
int finish_no_open(struct file *file, struct dentry *dentry)
|
2012-06-05 13:10:17 +00:00
|
|
|
{
|
2012-06-22 08:40:19 +00:00
|
|
|
file->f_path.dentry = dentry;
|
2018-07-09 23:17:52 +00:00
|
|
|
return 0;
|
2012-06-05 13:10:17 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(finish_no_open);
|
|
|
|
|
2015-06-19 08:29:13 +00:00
|
|
|
char *file_path(struct file *filp, char *buf, int buflen)
|
|
|
|
{
|
|
|
|
return d_path(&filp->f_path, buf, buflen);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(file_path);
|
|
|
|
|
2015-06-18 13:32:31 +00:00
|
|
|
/**
|
|
|
|
* vfs_open - open the file at the given path
|
|
|
|
* @path: path to open
|
|
|
|
* @file: newly allocated file with f_flag initialized
|
|
|
|
* @cred: credentials to use
|
|
|
|
*/
|
2018-07-10 17:22:28 +00:00
|
|
|
int vfs_open(const struct path *path, struct file *file)
|
2015-06-18 13:32:31 +00:00
|
|
|
{
|
2016-05-10 23:16:37 +00:00
|
|
|
file->f_path = *path;
|
2018-07-06 21:57:06 +00:00
|
|
|
return do_dentry_open(file, d_backing_inode(path->dentry), NULL);
|
2015-06-18 13:32:31 +00:00
|
|
|
}
|
|
|
|
|
2012-06-26 17:58:53 +00:00
|
|
|
struct file *dentry_open(const struct path *path, int flags,
|
2008-11-13 23:39:22 +00:00
|
|
|
const struct cred *cred)
|
[PATCH] open returns ENFILE but creates file anyway
When open(O_CREAT) is called and the error, ENFILE, is returned, the file
may be created anyway. This is counter intuitive, against the SUS V3
specification, and may cause applications to misbehave if they are not
coded correctly to handle this semantic. The SUS V3 specification
explicitly states "No files shall be created or modified if the function
returns -1.".
The error, ENFILE, is used to indicate the system wide open file table is
full and no more file structs can be allocated.
This is due to an ordering problem. The entry in the directory is created
before the file struct is allocated. If the allocation for the file struct
fails, then the system call must return an error, but the directory entry
was already created and can not be safely removed.
The solution to this situation is relatively easy. The file struct should
be allocated before the directory entry is created. If the allocation
fails, then the error can be returned directly. If the creation of the
directory entry fails, then the file struct can be easily freed.
Signed-off-by: Peter Staubach <staubach@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-09-13 08:25:12 +00:00
|
|
|
{
|
|
|
|
int error;
|
|
|
|
struct file *f;
|
|
|
|
|
2009-09-02 08:13:40 +00:00
|
|
|
validate_creds(cred);
|
|
|
|
|
2011-01-19 12:08:41 +00:00
|
|
|
/* We must always pass in a valid mount pointer. */
|
2012-06-26 17:58:53 +00:00
|
|
|
BUG_ON(!path->mnt);
|
2008-02-15 22:37:24 +00:00
|
|
|
|
2018-07-11 19:00:04 +00:00
|
|
|
f = alloc_empty_file(flags, cred);
|
Revert "fs: fold open_check_o_direct into do_dentry_open"
This reverts commit cab64df194667dc5d9d786f0a895f647f5501c0d.
Having vfs_open() in some cases drop the reference to
struct file combined with
error = vfs_open(path, f, cred);
if (error) {
put_filp(f);
return ERR_PTR(error);
}
return f;
is flat-out wrong. It used to be
error = vfs_open(path, f, cred);
if (!error) {
/* from now on we need fput() to dispose of f */
error = open_check_o_direct(f);
if (error) {
fput(f);
f = ERR_PTR(error);
}
} else {
put_filp(f);
f = ERR_PTR(error);
}
and sure, having that open_check_o_direct() boilerplate gotten rid of is
nice, but not that way...
Worse, another call chain (via finish_open()) is FUBAR now wrt
FILE_OPENED handling - in that case we get error returned, with file
already hit by fput() *AND* FILE_OPENED not set. Guess what happens in
path_openat(), when it hits
if (!(opened & FILE_OPENED)) {
BUG_ON(!error);
put_filp(file);
}
The root cause of all that crap is that the callers of do_dentry_open()
have no way to tell which way did it fail; while that could be fixed up
(by passing something like int *opened to do_dentry_open() and have it
marked if we'd called ->open()), it's probably much too late in the
cycle to do so right now.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-06-02 05:31:02 +00:00
|
|
|
if (!IS_ERR(f)) {
|
2018-07-10 17:22:28 +00:00
|
|
|
error = vfs_open(path, f);
|
2018-07-09 15:14:39 +00:00
|
|
|
if (error) {
|
|
|
|
fput(f);
|
Revert "fs: fold open_check_o_direct into do_dentry_open"
This reverts commit cab64df194667dc5d9d786f0a895f647f5501c0d.
Having vfs_open() in some cases drop the reference to
struct file combined with
error = vfs_open(path, f, cred);
if (error) {
put_filp(f);
return ERR_PTR(error);
}
return f;
is flat-out wrong. It used to be
error = vfs_open(path, f, cred);
if (!error) {
/* from now on we need fput() to dispose of f */
error = open_check_o_direct(f);
if (error) {
fput(f);
f = ERR_PTR(error);
}
} else {
put_filp(f);
f = ERR_PTR(error);
}
and sure, having that open_check_o_direct() boilerplate gotten rid of is
nice, but not that way...
Worse, another call chain (via finish_open()) is FUBAR now wrt
FILE_OPENED handling - in that case we get error returned, with file
already hit by fput() *AND* FILE_OPENED not set. Guess what happens in
path_openat(), when it hits
if (!(opened & FILE_OPENED)) {
BUG_ON(!error);
put_filp(file);
}
The root cause of all that crap is that the callers of do_dentry_open()
have no way to tell which way did it fail; while that could be fixed up
(by passing something like int *opened to do_dentry_open() and have it
marked if we'd called ->open()), it's probably much too late in the
cycle to do so right now.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2018-06-02 05:31:02 +00:00
|
|
|
f = ERR_PTR(error);
|
|
|
|
}
|
2012-06-10 18:24:38 +00:00
|
|
|
}
|
|
|
|
return f;
|
[PATCH] open returns ENFILE but creates file anyway
When open(O_CREAT) is called and the error, ENFILE, is returned, the file
may be created anyway. This is counter intuitive, against the SUS V3
specification, and may cause applications to misbehave if they are not
coded correctly to handle this semantic. The SUS V3 specification
explicitly states "No files shall be created or modified if the function
returns -1.".
The error, ENFILE, is used to indicate the system wide open file table is
full and no more file structs can be allocated.
This is due to an ordering problem. The entry in the directory is created
before the file struct is allocated. If the allocation for the file struct
fails, then the system call must return an error, but the directory entry
was already created and can not be safely removed.
The solution to this situation is relatively easy. The file struct should
be allocated before the directory entry is created. If the allocation
fails, then the error can be returned directly. If the creation of the
directory entry fails, then the file struct can be easily freed.
Signed-off-by: Peter Staubach <staubach@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-09-13 08:25:12 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
EXPORT_SYMBOL(dentry_open);
|
|
|
|
|
2018-07-12 15:18:42 +00:00
|
|
|
struct file *open_with_fake_path(const struct path *path, int flags,
|
|
|
|
struct inode *inode, const struct cred *cred)
|
|
|
|
{
|
2018-07-18 13:44:40 +00:00
|
|
|
struct file *f = alloc_empty_file_noaccount(flags, cred);
|
2018-07-12 15:18:42 +00:00
|
|
|
if (!IS_ERR(f)) {
|
|
|
|
int error;
|
|
|
|
|
|
|
|
f->f_path = *path;
|
|
|
|
error = do_dentry_open(f, inode, NULL);
|
|
|
|
if (error) {
|
|
|
|
fput(f);
|
|
|
|
f = ERR_PTR(error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(open_with_fake_path);
|
|
|
|
|
2011-11-21 19:59:34 +00:00
|
|
|
static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op)
|
2011-02-23 22:44:09 +00:00
|
|
|
{
|
|
|
|
int lookup_flags = 0;
|
2015-12-27 03:33:24 +00:00
|
|
|
int acc_mode = ACC_MODE(flags);
|
2011-02-23 22:44:09 +00:00
|
|
|
|
2017-04-27 07:42:25 +00:00
|
|
|
/*
|
|
|
|
* Clear out all open flags we don't know about so that we don't report
|
|
|
|
* them in fcntl(F_GETFD) or similar interfaces.
|
|
|
|
*/
|
|
|
|
flags &= VALID_OPEN_FLAGS;
|
|
|
|
|
2013-08-02 04:07:52 +00:00
|
|
|
if (flags & (O_CREAT | __O_TMPFILE))
|
2012-08-15 11:01:24 +00:00
|
|
|
op->mode = (mode & S_IALLUGO) | S_IFREG;
|
|
|
|
else
|
|
|
|
op->mode = 0;
|
2011-02-23 22:44:09 +00:00
|
|
|
|
|
|
|
/* Must never be set by userspace */
|
2012-08-26 15:01:04 +00:00
|
|
|
flags &= ~FMODE_NONOTIFY & ~O_CLOEXEC;
|
2011-02-23 22:44:09 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only
|
|
|
|
* check for O_DSYNC if the need any syncing at all we enforce it's
|
|
|
|
* always set instead of having to deal with possibly weird behaviour
|
|
|
|
* for malicious applications setting only __O_SYNC.
|
|
|
|
*/
|
|
|
|
if (flags & __O_SYNC)
|
|
|
|
flags |= O_DSYNC;
|
|
|
|
|
2013-07-13 09:26:37 +00:00
|
|
|
if (flags & __O_TMPFILE) {
|
|
|
|
if ((flags & O_TMPFILE_MASK) != O_TMPFILE)
|
2013-06-07 05:20:27 +00:00
|
|
|
return -EINVAL;
|
2013-07-19 23:11:32 +00:00
|
|
|
if (!(acc_mode & MAY_WRITE))
|
|
|
|
return -EINVAL;
|
2013-06-07 05:20:27 +00:00
|
|
|
} else if (flags & O_PATH) {
|
|
|
|
/*
|
|
|
|
* If we have O_PATH in the open flag. Then we
|
|
|
|
* cannot have anything other than the below set of flags
|
|
|
|
*/
|
New kind of open files - "location only".
New flag for open(2) - O_PATH. Semantics:
* pathname is resolved, but the file itself is _NOT_ opened
as far as filesystem is concerned.
* almost all operations on the resulting descriptors shall
fail with -EBADF. Exceptions are:
1) operations on descriptors themselves (i.e.
close(), dup(), dup2(), dup3(), fcntl(fd, F_DUPFD),
fcntl(fd, F_DUPFD_CLOEXEC, ...), fcntl(fd, F_GETFD),
fcntl(fd, F_SETFD, ...))
2) fcntl(fd, F_GETFL), for a common non-destructive way to
check if descriptor is open
3) "dfd" arguments of ...at(2) syscalls, i.e. the starting
points of pathname resolution
* closing such descriptor does *NOT* affect dnotify or
posix locks.
* permissions are checked as usual along the way to file;
no permission checks are applied to the file itself. Of course,
giving such thing to syscall will result in permission checks (at
the moment it means checking that starting point of ....at() is
a directory and caller has exec permissions on it).
fget() and fget_light() return NULL on such descriptors; use of
fget_raw() and fget_raw_light() is needed to get them. That protects
existing code from dealing with those things.
There are two things still missing (they come in the next commits):
one is handling of symlinks (right now we refuse to open them that
way; see the next commit for semantics related to those) and another
is descriptor passing via SCM_RIGHTS datagrams.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2011-03-13 07:51:11 +00:00
|
|
|
flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;
|
|
|
|
acc_mode = 0;
|
|
|
|
}
|
2011-02-23 22:44:09 +00:00
|
|
|
|
New kind of open files - "location only".
New flag for open(2) - O_PATH. Semantics:
* pathname is resolved, but the file itself is _NOT_ opened
as far as filesystem is concerned.
* almost all operations on the resulting descriptors shall
fail with -EBADF. Exceptions are:
1) operations on descriptors themselves (i.e.
close(), dup(), dup2(), dup3(), fcntl(fd, F_DUPFD),
fcntl(fd, F_DUPFD_CLOEXEC, ...), fcntl(fd, F_GETFD),
fcntl(fd, F_SETFD, ...))
2) fcntl(fd, F_GETFL), for a common non-destructive way to
check if descriptor is open
3) "dfd" arguments of ...at(2) syscalls, i.e. the starting
points of pathname resolution
* closing such descriptor does *NOT* affect dnotify or
posix locks.
* permissions are checked as usual along the way to file;
no permission checks are applied to the file itself. Of course,
giving such thing to syscall will result in permission checks (at
the moment it means checking that starting point of ....at() is
a directory and caller has exec permissions on it).
fget() and fget_light() return NULL on such descriptors; use of
fget_raw() and fget_raw_light() is needed to get them. That protects
existing code from dealing with those things.
There are two things still missing (they come in the next commits):
one is handling of symlinks (right now we refuse to open them that
way; see the next commit for semantics related to those) and another
is descriptor passing via SCM_RIGHTS datagrams.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2011-03-13 07:51:11 +00:00
|
|
|
op->open_flag = flags;
|
2011-02-23 22:44:09 +00:00
|
|
|
|
|
|
|
/* O_TRUNC implies we need access checks for write permissions */
|
|
|
|
if (flags & O_TRUNC)
|
|
|
|
acc_mode |= MAY_WRITE;
|
|
|
|
|
|
|
|
/* Allow the LSM permission hook to distinguish append
|
|
|
|
access from general write access. */
|
|
|
|
if (flags & O_APPEND)
|
|
|
|
acc_mode |= MAY_APPEND;
|
|
|
|
|
|
|
|
op->acc_mode = acc_mode;
|
|
|
|
|
New kind of open files - "location only".
New flag for open(2) - O_PATH. Semantics:
* pathname is resolved, but the file itself is _NOT_ opened
as far as filesystem is concerned.
* almost all operations on the resulting descriptors shall
fail with -EBADF. Exceptions are:
1) operations on descriptors themselves (i.e.
close(), dup(), dup2(), dup3(), fcntl(fd, F_DUPFD),
fcntl(fd, F_DUPFD_CLOEXEC, ...), fcntl(fd, F_GETFD),
fcntl(fd, F_SETFD, ...))
2) fcntl(fd, F_GETFL), for a common non-destructive way to
check if descriptor is open
3) "dfd" arguments of ...at(2) syscalls, i.e. the starting
points of pathname resolution
* closing such descriptor does *NOT* affect dnotify or
posix locks.
* permissions are checked as usual along the way to file;
no permission checks are applied to the file itself. Of course,
giving such thing to syscall will result in permission checks (at
the moment it means checking that starting point of ....at() is
a directory and caller has exec permissions on it).
fget() and fget_light() return NULL on such descriptors; use of
fget_raw() and fget_raw_light() is needed to get them. That protects
existing code from dealing with those things.
There are two things still missing (they come in the next commits):
one is handling of symlinks (right now we refuse to open them that
way; see the next commit for semantics related to those) and another
is descriptor passing via SCM_RIGHTS datagrams.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2011-03-13 07:51:11 +00:00
|
|
|
op->intent = flags & O_PATH ? 0 : LOOKUP_OPEN;
|
|
|
|
|
2011-02-23 22:44:09 +00:00
|
|
|
if (flags & O_CREAT) {
|
|
|
|
op->intent |= LOOKUP_CREATE;
|
|
|
|
if (flags & O_EXCL)
|
|
|
|
op->intent |= LOOKUP_EXCL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & O_DIRECTORY)
|
|
|
|
lookup_flags |= LOOKUP_DIRECTORY;
|
|
|
|
if (!(flags & O_NOFOLLOW))
|
|
|
|
lookup_flags |= LOOKUP_FOLLOW;
|
2013-06-11 04:23:01 +00:00
|
|
|
op->lookup_flags = lookup_flags;
|
|
|
|
return 0;
|
2011-02-23 22:44:09 +00:00
|
|
|
}
|
|
|
|
|
2012-10-10 20:43:10 +00:00
|
|
|
/**
|
|
|
|
* file_open_name - open file and return file pointer
|
|
|
|
*
|
|
|
|
* @name: struct filename containing path to open
|
|
|
|
* @flags: open flags as per the open(2) second argument
|
|
|
|
* @mode: mode for the new file if O_CREAT is set, else ignored
|
|
|
|
*
|
|
|
|
* This is the helper to open a file from kernelspace if you really
|
|
|
|
* have to. But in generally you should not do this, so please move
|
|
|
|
* along, nothing to see here..
|
|
|
|
*/
|
|
|
|
struct file *file_open_name(struct filename *name, int flags, umode_t mode)
|
|
|
|
{
|
|
|
|
struct open_flags op;
|
2013-06-11 04:23:01 +00:00
|
|
|
int err = build_open_flags(flags, mode, &op);
|
|
|
|
return err ? ERR_PTR(err) : do_filp_open(AT_FDCWD, name, &op);
|
2012-10-10 20:43:10 +00:00
|
|
|
}
|
|
|
|
|
2011-02-23 22:44:09 +00:00
|
|
|
/**
|
|
|
|
* filp_open - open file and return file pointer
|
|
|
|
*
|
|
|
|
* @filename: path to open
|
|
|
|
* @flags: open flags as per the open(2) second argument
|
|
|
|
* @mode: mode for the new file if O_CREAT is set, else ignored
|
|
|
|
*
|
|
|
|
* This is the helper to open a file from kernelspace if you really
|
|
|
|
* have to. But in generally you should not do this, so please move
|
|
|
|
* along, nothing to see here..
|
|
|
|
*/
|
2011-11-21 19:59:34 +00:00
|
|
|
struct file *filp_open(const char *filename, int flags, umode_t mode)
|
2011-02-23 22:44:09 +00:00
|
|
|
{
|
2015-01-22 05:00:03 +00:00
|
|
|
struct filename *name = getname_kernel(filename);
|
|
|
|
struct file *file = ERR_CAST(name);
|
|
|
|
|
|
|
|
if (!IS_ERR(name)) {
|
|
|
|
file = file_open_name(name, flags, mode);
|
|
|
|
putname(name);
|
|
|
|
}
|
|
|
|
return file;
|
2011-02-23 22:44:09 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(filp_open);
|
|
|
|
|
2011-03-11 17:08:24 +00:00
|
|
|
struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
|
2016-03-22 21:25:36 +00:00
|
|
|
const char *filename, int flags, umode_t mode)
|
2011-03-11 17:08:24 +00:00
|
|
|
{
|
|
|
|
struct open_flags op;
|
2016-03-22 21:25:36 +00:00
|
|
|
int err = build_open_flags(flags, mode, &op);
|
2013-06-11 04:23:01 +00:00
|
|
|
if (err)
|
|
|
|
return ERR_PTR(err);
|
|
|
|
return do_file_open_root(dentry, mnt, filename, &op);
|
2011-03-11 17:08:24 +00:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(file_open_root);
|
|
|
|
|
2011-11-21 19:59:34 +00:00
|
|
|
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2011-02-23 22:44:09 +00:00
|
|
|
struct open_flags op;
|
2013-06-11 04:23:01 +00:00
|
|
|
int fd = build_open_flags(flags, mode, &op);
|
|
|
|
struct filename *tmp;
|
|
|
|
|
|
|
|
if (fd)
|
|
|
|
return fd;
|
|
|
|
|
|
|
|
tmp = getname(filename);
|
|
|
|
if (IS_ERR(tmp))
|
|
|
|
return PTR_ERR(tmp);
|
|
|
|
|
|
|
|
fd = get_unused_fd_flags(flags);
|
|
|
|
if (fd >= 0) {
|
|
|
|
struct file *f = do_filp_open(dfd, tmp, &op);
|
|
|
|
if (IS_ERR(f)) {
|
|
|
|
put_unused_fd(fd);
|
|
|
|
fd = PTR_ERR(f);
|
|
|
|
} else {
|
|
|
|
fsnotify_open(f);
|
|
|
|
fd_install(fd, f);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
}
|
2013-06-11 04:23:01 +00:00
|
|
|
putname(tmp);
|
2005-04-16 22:20:36 +00:00
|
|
|
return fd;
|
|
|
|
}
|
2005-09-06 22:18:25 +00:00
|
|
|
|
2011-11-21 19:59:34 +00:00
|
|
|
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
|
2005-09-06 22:18:25 +00:00
|
|
|
{
|
|
|
|
if (force_o_largefile())
|
|
|
|
flags |= O_LARGEFILE;
|
|
|
|
|
2013-01-21 20:25:54 +00:00
|
|
|
return do_sys_open(AT_FDCWD, filename, flags, mode);
|
2005-09-06 22:18:25 +00:00
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
|
2009-01-14 13:14:32 +00:00
|
|
|
SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags,
|
2011-11-21 19:59:34 +00:00
|
|
|
umode_t, mode)
|
2006-01-19 01:43:53 +00:00
|
|
|
{
|
|
|
|
if (force_o_largefile())
|
|
|
|
flags |= O_LARGEFILE;
|
|
|
|
|
2013-01-21 20:25:54 +00:00
|
|
|
return do_sys_open(dfd, filename, flags, mode);
|
2006-01-19 01:43:53 +00:00
|
|
|
}
|
|
|
|
|
2017-04-08 22:15:12 +00:00
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
/*
|
|
|
|
* Exactly like sys_open(), except that it doesn't set the
|
|
|
|
* O_LARGEFILE flag.
|
|
|
|
*/
|
|
|
|
COMPAT_SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
|
|
|
|
{
|
|
|
|
return do_sys_open(AT_FDCWD, filename, flags, mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Exactly like sys_openat(), except that it doesn't set the
|
|
|
|
* O_LARGEFILE flag.
|
|
|
|
*/
|
|
|
|
COMPAT_SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, umode_t, mode)
|
|
|
|
{
|
|
|
|
return do_sys_open(dfd, filename, flags, mode);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-04-16 22:20:36 +00:00
|
|
|
#ifndef __alpha__
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For backward compatibility? Maybe this should be moved
|
|
|
|
* into arch/i386 instead?
|
|
|
|
*/
|
2011-11-21 19:59:34 +00:00
|
|
|
SYSCALL_DEFINE2(creat, const char __user *, pathname, umode_t, mode)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2018-03-11 10:34:56 +00:00
|
|
|
return ksys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "id" is the POSIX thread ID. We use the
|
|
|
|
* files pointer for this..
|
|
|
|
*/
|
|
|
|
int filp_close(struct file *filp, fl_owner_t id)
|
|
|
|
{
|
2005-06-23 07:10:17 +00:00
|
|
|
int retval = 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
|
|
|
|
if (!file_count(filp)) {
|
|
|
|
printk(KERN_ERR "VFS: Close: file count is 0\n");
|
2005-06-23 07:10:17 +00:00
|
|
|
return 0;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
2013-09-22 20:27:52 +00:00
|
|
|
if (filp->f_op->flush)
|
2006-06-23 09:05:12 +00:00
|
|
|
retval = filp->f_op->flush(filp, id);
|
2005-04-16 22:20:36 +00:00
|
|
|
|
New kind of open files - "location only".
New flag for open(2) - O_PATH. Semantics:
* pathname is resolved, but the file itself is _NOT_ opened
as far as filesystem is concerned.
* almost all operations on the resulting descriptors shall
fail with -EBADF. Exceptions are:
1) operations on descriptors themselves (i.e.
close(), dup(), dup2(), dup3(), fcntl(fd, F_DUPFD),
fcntl(fd, F_DUPFD_CLOEXEC, ...), fcntl(fd, F_GETFD),
fcntl(fd, F_SETFD, ...))
2) fcntl(fd, F_GETFL), for a common non-destructive way to
check if descriptor is open
3) "dfd" arguments of ...at(2) syscalls, i.e. the starting
points of pathname resolution
* closing such descriptor does *NOT* affect dnotify or
posix locks.
* permissions are checked as usual along the way to file;
no permission checks are applied to the file itself. Of course,
giving such thing to syscall will result in permission checks (at
the moment it means checking that starting point of ....at() is
a directory and caller has exec permissions on it).
fget() and fget_light() return NULL on such descriptors; use of
fget_raw() and fget_raw_light() is needed to get them. That protects
existing code from dealing with those things.
There are two things still missing (they come in the next commits):
one is handling of symlinks (right now we refuse to open them that
way; see the next commit for semantics related to those) and another
is descriptor passing via SCM_RIGHTS datagrams.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2011-03-13 07:51:11 +00:00
|
|
|
if (likely(!(filp->f_mode & FMODE_PATH))) {
|
|
|
|
dnotify_flush(filp, id);
|
|
|
|
locks_remove_posix(filp, id);
|
|
|
|
}
|
2005-04-16 22:20:36 +00:00
|
|
|
fput(filp);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
EXPORT_SYMBOL(filp_close);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Careful here! We test whether the file pointer is NULL before
|
|
|
|
* releasing the fd. This ensures that one clone task can't release
|
|
|
|
* an fd while another clone is opening it.
|
|
|
|
*/
|
2009-01-14 13:14:19 +00:00
|
|
|
SYSCALL_DEFINE1(close, unsigned int, fd)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
2012-08-19 16:04:24 +00:00
|
|
|
int retval = __close_fd(current->files, fd);
|
2006-09-29 09:00:13 +00:00
|
|
|
|
|
|
|
/* can't restart close syscall because file table entry was cleared */
|
|
|
|
if (unlikely(retval == -ERESTARTSYS ||
|
|
|
|
retval == -ERESTARTNOINTR ||
|
|
|
|
retval == -ERESTARTNOHAND ||
|
|
|
|
retval == -ERESTART_RESTARTBLOCK))
|
|
|
|
retval = -EINTR;
|
|
|
|
|
|
|
|
return retval;
|
2005-04-16 22:20:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This routine simulates a hangup on the tty, to arrange that users
|
|
|
|
* are given clean terminals at login time.
|
|
|
|
*/
|
2009-01-14 13:14:19 +00:00
|
|
|
SYSCALL_DEFINE0(vhangup)
|
2005-04-16 22:20:36 +00:00
|
|
|
{
|
|
|
|
if (capable(CAP_SYS_TTY_CONFIG)) {
|
2008-10-13 09:40:30 +00:00
|
|
|
tty_vhangup_self();
|
2005-04-16 22:20:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -EPERM;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called when an inode is about to be open.
|
|
|
|
* We use this to disallow opening large files on 32bit systems if
|
|
|
|
* the caller didn't specify O_LARGEFILE. On 64bit systems we force
|
|
|
|
* on this flag in sys_open.
|
|
|
|
*/
|
|
|
|
int generic_file_open(struct inode * inode, struct file * filp)
|
|
|
|
{
|
|
|
|
if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
|
2007-10-17 06:30:22 +00:00
|
|
|
return -EOVERFLOW;
|
2005-04-16 22:20:36 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
EXPORT_SYMBOL(generic_file_open);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is used by subsystems that don't want seekable
|
2010-08-11 01:01:33 +00:00
|
|
|
* file descriptors. The function is not supposed to ever fail, the only
|
|
|
|
* reason it returns an 'int' and not 'void' is so that it can be plugged
|
|
|
|
* directly into file_operations structure.
|
2005-04-16 22:20:36 +00:00
|
|
|
*/
|
|
|
|
int nonseekable_open(struct inode *inode, struct file *filp)
|
|
|
|
{
|
|
|
|
filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
EXPORT_SYMBOL(nonseekable_open);
|
fs: stream_open - opener for stream-like files so that read and write can run simultaneously without deadlock
Commit 9c225f2655e3 ("vfs: atomic f_pos accesses as per POSIX") added
locking for file.f_pos access and in particular made concurrent read and
write not possible - now both those functions take f_pos lock for the
whole run, and so if e.g. a read is blocked waiting for data, write will
deadlock waiting for that read to complete.
This caused regression for stream-like files where previously read and
write could run simultaneously, but after that patch could not do so
anymore. See e.g. commit 581d21a2d02a ("xenbus: fix deadlock on writes
to /proc/xen/xenbus") which fixes such regression for particular case of
/proc/xen/xenbus.
The patch that added f_pos lock in 2014 did so to guarantee POSIX thread
safety for read/write/lseek and added the locking to file descriptors of
all regular files. In 2014 that thread-safety problem was not new as it
was already discussed earlier in 2006.
However even though 2006'th version of Linus's patch was adding f_pos
locking "only for files that are marked seekable with FMODE_LSEEK (thus
avoiding the stream-like objects like pipes and sockets)", the 2014
version - the one that actually made it into the tree as 9c225f2655e3 -
is doing so irregardless of whether a file is seekable or not.
See
https://lore.kernel.org/lkml/53022DB1.4070805@gmail.com/
https://lwn.net/Articles/180387
https://lwn.net/Articles/180396
for historic context.
The reason that it did so is, probably, that there are many files that
are marked non-seekable, but e.g. their read implementation actually
depends on knowing current position to correctly handle the read. Some
examples:
kernel/power/user.c snapshot_read
fs/debugfs/file.c u32_array_read
fs/fuse/control.c fuse_conn_waiting_read + ...
drivers/hwmon/asus_atk0110.c atk_debugfs_ggrp_read
arch/s390/hypfs/inode.c hypfs_read_iter
...
Despite that, many nonseekable_open users implement read and write with
pure stream semantics - they don't depend on passed ppos at all. And for
those cases where read could wait for something inside, it creates a
situation similar to xenbus - the write could be never made to go until
read is done, and read is waiting for some, potentially external, event,
for potentially unbounded time -> deadlock.
Besides xenbus, there are 14 such places in the kernel that I've found
with semantic patch (see below):
drivers/xen/evtchn.c:667:8-24: ERROR: evtchn_fops: .read() can deadlock .write()
drivers/isdn/capi/capi.c:963:8-24: ERROR: capi_fops: .read() can deadlock .write()
drivers/input/evdev.c:527:1-17: ERROR: evdev_fops: .read() can deadlock .write()
drivers/char/pcmcia/cm4000_cs.c:1685:7-23: ERROR: cm4000_fops: .read() can deadlock .write()
net/rfkill/core.c:1146:8-24: ERROR: rfkill_fops: .read() can deadlock .write()
drivers/s390/char/fs3270.c:488:1-17: ERROR: fs3270_fops: .read() can deadlock .write()
drivers/usb/misc/ldusb.c:310:1-17: ERROR: ld_usb_fops: .read() can deadlock .write()
drivers/hid/uhid.c:635:1-17: ERROR: uhid_fops: .read() can deadlock .write()
net/batman-adv/icmp_socket.c:80:1-17: ERROR: batadv_fops: .read() can deadlock .write()
drivers/media/rc/lirc_dev.c:198:1-17: ERROR: lirc_fops: .read() can deadlock .write()
drivers/leds/uleds.c:77:1-17: ERROR: uleds_fops: .read() can deadlock .write()
drivers/input/misc/uinput.c:400:1-17: ERROR: uinput_fops: .read() can deadlock .write()
drivers/infiniband/core/user_mad.c:985:7-23: ERROR: umad_fops: .read() can deadlock .write()
drivers/gnss/core.c:45:1-17: ERROR: gnss_fops: .read() can deadlock .write()
In addition to the cases above another regression caused by f_pos
locking is that now FUSE filesystems that implement open with
FOPEN_NONSEEKABLE flag, can no longer implement bidirectional
stream-like files - for the same reason as above e.g. read can deadlock
write locking on file.f_pos in the kernel.
FUSE's FOPEN_NONSEEKABLE was added in 2008 in a7c1b990f715 ("fuse:
implement nonseekable open") to support OSSPD. OSSPD implements /dev/dsp
in userspace with FOPEN_NONSEEKABLE flag, with corresponding read and
write routines not depending on current position at all, and with both
read and write being potentially blocking operations:
See
https://github.com/libfuse/osspd
https://lwn.net/Articles/308445
https://github.com/libfuse/osspd/blob/14a9cff0/osspd.c#L1406
https://github.com/libfuse/osspd/blob/14a9cff0/osspd.c#L1438-L1477
https://github.com/libfuse/osspd/blob/14a9cff0/osspd.c#L1479-L1510
Corresponding libfuse example/test also describes FOPEN_NONSEEKABLE as
"somewhat pipe-like files ..." with read handler not using offset.
However that test implements only read without write and cannot exercise
the deadlock scenario:
https://github.com/libfuse/libfuse/blob/fuse-3.4.2-3-ga1bff7d/example/poll.c#L124-L131
https://github.com/libfuse/libfuse/blob/fuse-3.4.2-3-ga1bff7d/example/poll.c#L146-L163
https://github.com/libfuse/libfuse/blob/fuse-3.4.2-3-ga1bff7d/example/poll.c#L209-L216
I've actually hit the read vs write deadlock for real while implementing
my FUSE filesystem where there is /head/watch file, for which open
creates separate bidirectional socket-like stream in between filesystem
and its user with both read and write being later performed
simultaneously. And there it is semantically not easy to split the
stream into two separate read-only and write-only channels:
https://lab.nexedi.com/kirr/wendelin.core/blob/f13aa600/wcfs/wcfs.go#L88-169
Let's fix this regression. The plan is:
1. We can't change nonseekable_open to include &~FMODE_ATOMIC_POS -
doing so would break many in-kernel nonseekable_open users which
actually use ppos in read/write handlers.
2. Add stream_open() to kernel to open stream-like non-seekable file
descriptors. Read and write on such file descriptors would never use
nor change ppos. And with that property on stream-like files read and
write will be running without taking f_pos lock - i.e. read and write
could be running simultaneously.
3. With semantic patch search and convert to stream_open all in-kernel
nonseekable_open users for which read and write actually do not
depend on ppos and where there is no other methods in file_operations
which assume @offset access.
4. Add FOPEN_STREAM to fs/fuse/ and open in-kernel file-descriptors via
steam_open if that bit is present in filesystem open reply.
It was tempting to change fs/fuse/ open handler to use stream_open
instead of nonseekable_open on just FOPEN_NONSEEKABLE flags, but
grepping through Debian codesearch shows users of FOPEN_NONSEEKABLE,
and in particular GVFS which actually uses offset in its read and
write handlers
https://codesearch.debian.net/search?q=-%3Enonseekable+%3D
https://gitlab.gnome.org/GNOME/gvfs/blob/1.40.0-6-gcbc54396/client/gvfsfusedaemon.c#L1080
https://gitlab.gnome.org/GNOME/gvfs/blob/1.40.0-6-gcbc54396/client/gvfsfusedaemon.c#L1247-1346
https://gitlab.gnome.org/GNOME/gvfs/blob/1.40.0-6-gcbc54396/client/gvfsfusedaemon.c#L1399-1481
so if we would do such a change it will break a real user.
5. Add stream_open and FOPEN_STREAM handling to stable kernels starting
from v3.14+ (the kernel where 9c225f2655 first appeared).
This will allow to patch OSSPD and other FUSE filesystems that
provide stream-like files to return FOPEN_STREAM | FOPEN_NONSEEKABLE
in their open handler and this way avoid the deadlock on all kernel
versions. This should work because fs/fuse/ ignores unknown open
flags returned from a filesystem and so passing FOPEN_STREAM to a
kernel that is not aware of this flag cannot hurt. In turn the kernel
that is not aware of FOPEN_STREAM will be < v3.14 where just
FOPEN_NONSEEKABLE is sufficient to implement streams without read vs
write deadlock.
This patch adds stream_open, converts /proc/xen/xenbus to it and adds
semantic patch to automatically locate in-kernel places that are either
required to be converted due to read vs write deadlock, or that are just
safe to be converted because read and write do not use ppos and there
are no other funky methods in file_operations.
Regarding semantic patch I've verified each generated change manually -
that it is correct to convert - and each other nonseekable_open instance
left - that it is either not correct to convert there, or that it is not
converted due to current stream_open.cocci limitations.
The script also does not convert files that should be valid to convert,
but that currently have .llseek = noop_llseek or generic_file_llseek for
unknown reason despite file being opened with nonseekable_open (e.g.
drivers/input/mousedev.c)
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Yongzhi Pan <panyongzhi@gmail.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: David Vrabel <david.vrabel@citrix.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Miklos Szeredi <miklos@szeredi.hu>
Cc: Tejun Heo <tj@kernel.org>
Cc: Kirill Tkhai <ktkhai@virtuozzo.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Julia Lawall <Julia.Lawall@lip6.fr>
Cc: Nikolaus Rath <Nikolaus@rath.org>
Cc: Han-Wen Nienhuys <hanwen@google.com>
Signed-off-by: Kirill Smelkov <kirr@nexedi.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2019-03-26 22:20:43 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* stream_open is used by subsystems that want stream-like file descriptors.
|
|
|
|
* Such file descriptors are not seekable and don't have notion of position
|
2019-04-12 09:31:57 +00:00
|
|
|
* (file.f_pos is always 0 and ppos passed to .read()/.write() is always NULL).
|
|
|
|
* Contrary to file descriptors of other regular files, .read() and .write()
|
|
|
|
* can run simultaneously.
|
fs: stream_open - opener for stream-like files so that read and write can run simultaneously without deadlock
Commit 9c225f2655e3 ("vfs: atomic f_pos accesses as per POSIX") added
locking for file.f_pos access and in particular made concurrent read and
write not possible - now both those functions take f_pos lock for the
whole run, and so if e.g. a read is blocked waiting for data, write will
deadlock waiting for that read to complete.
This caused regression for stream-like files where previously read and
write could run simultaneously, but after that patch could not do so
anymore. See e.g. commit 581d21a2d02a ("xenbus: fix deadlock on writes
to /proc/xen/xenbus") which fixes such regression for particular case of
/proc/xen/xenbus.
The patch that added f_pos lock in 2014 did so to guarantee POSIX thread
safety for read/write/lseek and added the locking to file descriptors of
all regular files. In 2014 that thread-safety problem was not new as it
was already discussed earlier in 2006.
However even though 2006'th version of Linus's patch was adding f_pos
locking "only for files that are marked seekable with FMODE_LSEEK (thus
avoiding the stream-like objects like pipes and sockets)", the 2014
version - the one that actually made it into the tree as 9c225f2655e3 -
is doing so irregardless of whether a file is seekable or not.
See
https://lore.kernel.org/lkml/53022DB1.4070805@gmail.com/
https://lwn.net/Articles/180387
https://lwn.net/Articles/180396
for historic context.
The reason that it did so is, probably, that there are many files that
are marked non-seekable, but e.g. their read implementation actually
depends on knowing current position to correctly handle the read. Some
examples:
kernel/power/user.c snapshot_read
fs/debugfs/file.c u32_array_read
fs/fuse/control.c fuse_conn_waiting_read + ...
drivers/hwmon/asus_atk0110.c atk_debugfs_ggrp_read
arch/s390/hypfs/inode.c hypfs_read_iter
...
Despite that, many nonseekable_open users implement read and write with
pure stream semantics - they don't depend on passed ppos at all. And for
those cases where read could wait for something inside, it creates a
situation similar to xenbus - the write could be never made to go until
read is done, and read is waiting for some, potentially external, event,
for potentially unbounded time -> deadlock.
Besides xenbus, there are 14 such places in the kernel that I've found
with semantic patch (see below):
drivers/xen/evtchn.c:667:8-24: ERROR: evtchn_fops: .read() can deadlock .write()
drivers/isdn/capi/capi.c:963:8-24: ERROR: capi_fops: .read() can deadlock .write()
drivers/input/evdev.c:527:1-17: ERROR: evdev_fops: .read() can deadlock .write()
drivers/char/pcmcia/cm4000_cs.c:1685:7-23: ERROR: cm4000_fops: .read() can deadlock .write()
net/rfkill/core.c:1146:8-24: ERROR: rfkill_fops: .read() can deadlock .write()
drivers/s390/char/fs3270.c:488:1-17: ERROR: fs3270_fops: .read() can deadlock .write()
drivers/usb/misc/ldusb.c:310:1-17: ERROR: ld_usb_fops: .read() can deadlock .write()
drivers/hid/uhid.c:635:1-17: ERROR: uhid_fops: .read() can deadlock .write()
net/batman-adv/icmp_socket.c:80:1-17: ERROR: batadv_fops: .read() can deadlock .write()
drivers/media/rc/lirc_dev.c:198:1-17: ERROR: lirc_fops: .read() can deadlock .write()
drivers/leds/uleds.c:77:1-17: ERROR: uleds_fops: .read() can deadlock .write()
drivers/input/misc/uinput.c:400:1-17: ERROR: uinput_fops: .read() can deadlock .write()
drivers/infiniband/core/user_mad.c:985:7-23: ERROR: umad_fops: .read() can deadlock .write()
drivers/gnss/core.c:45:1-17: ERROR: gnss_fops: .read() can deadlock .write()
In addition to the cases above another regression caused by f_pos
locking is that now FUSE filesystems that implement open with
FOPEN_NONSEEKABLE flag, can no longer implement bidirectional
stream-like files - for the same reason as above e.g. read can deadlock
write locking on file.f_pos in the kernel.
FUSE's FOPEN_NONSEEKABLE was added in 2008 in a7c1b990f715 ("fuse:
implement nonseekable open") to support OSSPD. OSSPD implements /dev/dsp
in userspace with FOPEN_NONSEEKABLE flag, with corresponding read and
write routines not depending on current position at all, and with both
read and write being potentially blocking operations:
See
https://github.com/libfuse/osspd
https://lwn.net/Articles/308445
https://github.com/libfuse/osspd/blob/14a9cff0/osspd.c#L1406
https://github.com/libfuse/osspd/blob/14a9cff0/osspd.c#L1438-L1477
https://github.com/libfuse/osspd/blob/14a9cff0/osspd.c#L1479-L1510
Corresponding libfuse example/test also describes FOPEN_NONSEEKABLE as
"somewhat pipe-like files ..." with read handler not using offset.
However that test implements only read without write and cannot exercise
the deadlock scenario:
https://github.com/libfuse/libfuse/blob/fuse-3.4.2-3-ga1bff7d/example/poll.c#L124-L131
https://github.com/libfuse/libfuse/blob/fuse-3.4.2-3-ga1bff7d/example/poll.c#L146-L163
https://github.com/libfuse/libfuse/blob/fuse-3.4.2-3-ga1bff7d/example/poll.c#L209-L216
I've actually hit the read vs write deadlock for real while implementing
my FUSE filesystem where there is /head/watch file, for which open
creates separate bidirectional socket-like stream in between filesystem
and its user with both read and write being later performed
simultaneously. And there it is semantically not easy to split the
stream into two separate read-only and write-only channels:
https://lab.nexedi.com/kirr/wendelin.core/blob/f13aa600/wcfs/wcfs.go#L88-169
Let's fix this regression. The plan is:
1. We can't change nonseekable_open to include &~FMODE_ATOMIC_POS -
doing so would break many in-kernel nonseekable_open users which
actually use ppos in read/write handlers.
2. Add stream_open() to kernel to open stream-like non-seekable file
descriptors. Read and write on such file descriptors would never use
nor change ppos. And with that property on stream-like files read and
write will be running without taking f_pos lock - i.e. read and write
could be running simultaneously.
3. With semantic patch search and convert to stream_open all in-kernel
nonseekable_open users for which read and write actually do not
depend on ppos and where there is no other methods in file_operations
which assume @offset access.
4. Add FOPEN_STREAM to fs/fuse/ and open in-kernel file-descriptors via
steam_open if that bit is present in filesystem open reply.
It was tempting to change fs/fuse/ open handler to use stream_open
instead of nonseekable_open on just FOPEN_NONSEEKABLE flags, but
grepping through Debian codesearch shows users of FOPEN_NONSEEKABLE,
and in particular GVFS which actually uses offset in its read and
write handlers
https://codesearch.debian.net/search?q=-%3Enonseekable+%3D
https://gitlab.gnome.org/GNOME/gvfs/blob/1.40.0-6-gcbc54396/client/gvfsfusedaemon.c#L1080
https://gitlab.gnome.org/GNOME/gvfs/blob/1.40.0-6-gcbc54396/client/gvfsfusedaemon.c#L1247-1346
https://gitlab.gnome.org/GNOME/gvfs/blob/1.40.0-6-gcbc54396/client/gvfsfusedaemon.c#L1399-1481
so if we would do such a change it will break a real user.
5. Add stream_open and FOPEN_STREAM handling to stable kernels starting
from v3.14+ (the kernel where 9c225f2655 first appeared).
This will allow to patch OSSPD and other FUSE filesystems that
provide stream-like files to return FOPEN_STREAM | FOPEN_NONSEEKABLE
in their open handler and this way avoid the deadlock on all kernel
versions. This should work because fs/fuse/ ignores unknown open
flags returned from a filesystem and so passing FOPEN_STREAM to a
kernel that is not aware of this flag cannot hurt. In turn the kernel
that is not aware of FOPEN_STREAM will be < v3.14 where just
FOPEN_NONSEEKABLE is sufficient to implement streams without read vs
write deadlock.
This patch adds stream_open, converts /proc/xen/xenbus to it and adds
semantic patch to automatically locate in-kernel places that are either
required to be converted due to read vs write deadlock, or that are just
safe to be converted because read and write do not use ppos and there
are no other funky methods in file_operations.
Regarding semantic patch I've verified each generated change manually -
that it is correct to convert - and each other nonseekable_open instance
left - that it is either not correct to convert there, or that it is not
converted due to current stream_open.cocci limitations.
The script also does not convert files that should be valid to convert,
but that currently have .llseek = noop_llseek or generic_file_llseek for
unknown reason despite file being opened with nonseekable_open (e.g.
drivers/input/mousedev.c)
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Yongzhi Pan <panyongzhi@gmail.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: David Vrabel <david.vrabel@citrix.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Miklos Szeredi <miklos@szeredi.hu>
Cc: Tejun Heo <tj@kernel.org>
Cc: Kirill Tkhai <ktkhai@virtuozzo.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Julia Lawall <Julia.Lawall@lip6.fr>
Cc: Nikolaus Rath <Nikolaus@rath.org>
Cc: Han-Wen Nienhuys <hanwen@google.com>
Signed-off-by: Kirill Smelkov <kirr@nexedi.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2019-03-26 22:20:43 +00:00
|
|
|
*
|
|
|
|
* stream_open never fails and is marked to return int so that it could be
|
|
|
|
* directly used as file_operations.open .
|
|
|
|
*/
|
|
|
|
int stream_open(struct inode *inode, struct file *filp)
|
|
|
|
{
|
|
|
|
filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE | FMODE_ATOMIC_POS);
|
|
|
|
filp->f_mode |= FMODE_STREAM;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
EXPORT_SYMBOL(stream_open);
|