/* * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README */ #include #include #include #include "reiserfs.h" #include #include #include #include /* * reiserfs_ioctl - handler for ioctl for inode * supported commands: * 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect * and prevent packing file (argument arg has t * be non-zero) * 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION * 3) That's all for a while ... */ long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct inode *inode = file_inode(filp); unsigned int flags; int err = 0; reiserfs_write_lock(inode->i_sb); switch (cmd) { case REISERFS_IOC_UNPACK: if (S_ISREG(inode->i_mode)) { if (arg) err = reiserfs_unpack(inode, filp); } else err = -ENOTTY; break; /* * following two cases are taken from fs/ext2/ioctl.c by Remy * Card (card@masi.ibp.fr) */ case REISERFS_IOC_GETFLAGS: if (!reiserfs_attrs(inode->i_sb)) { err = -ENOTTY; break; } flags = REISERFS_I(inode)->i_attrs; i_attrs_to_sd_attrs(inode, (__u16 *) & flags); err = put_user(flags, (int __user *)arg); break; case REISERFS_IOC_SETFLAGS:{ if (!reiserfs_attrs(inode->i_sb)) { err = -ENOTTY; break; } err = mnt_want_write_file(filp); if (err) break; if (!inode_owner_or_capable(inode)) { err = -EPERM; goto setflags_out; } if (get_user(flags, (int __user *)arg)) { err = -EFAULT; goto setflags_out; } /* * Is it quota file? Do not allow user to mess with it */ if (IS_NOQUOTA(inode)) { err = -EPERM; goto setflags_out; } if (((flags ^ REISERFS_I(inode)-> i_attrs) & (REISERFS_IMMUTABLE_FL | REISERFS_APPEND_FL)) && !capable(CAP_LINUX_IMMUTABLE)) { err = -EPERM; goto setflags_out; } if ((flags & REISERFS_NOTAIL_FL) && S_ISREG(inode->i_mode)) { int result; result = reiserfs_unpack(inode, filp); if (result) { err = result; goto setflags_out; } } sd_attrs_to_i_attrs(flags, inode); REISERFS_I(inode)->i_attrs = flags; inode->i_ctime = current_time(inode); mark_inode_dirty(inode); setflags_out: mnt_drop_write_file(filp); break; } case REISERFS_IOC_GETVERSION: err = put_user(inode->i_generation, (int __user *)arg); break; case REISERFS_IOC_SETVERSION: if (!inode_owner_or_capable(inode)) { err = -EPERM; break; } err = mnt_want_write_file(filp); if (err) break; if (get_user(inode->i_generation, (int __user *)arg)) { err = -EFAULT; goto setversion_out; } inode->i_ctime = current_time(inode); mark_inode_dirty(inode); setversion_out: mnt_drop_write_file(filp); break; default: err = -ENOTTY; } reiserfs_write_unlock(inode->i_sb); return err; } #ifdef CONFIG_COMPAT long reiserfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { /* * These are just misnamed, they actually * get/put from/to user an int */ switch (cmd) { case REISERFS_IOC32_UNPACK: cmd = REISERFS_IOC_UNPACK; break; case REISERFS_IOC32_GETFLAGS: cmd = REISERFS_IOC_GETFLAGS; break; case REISERFS_IOC32_SETFLAGS: cmd = REISERFS_IOC_SETFLAGS; break; case REISERFS_IOC32_GETVERSION: cmd = REISERFS_IOC_GETVERSION; break; case REISERFS_IOC32_SETVERSION: cmd = REISERFS_IOC_SETVERSION; break; default: return -ENOIOCTLCMD; } return reiserfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); } #endif int reiserfs_commit_write(struct file *f, struct page *page, unsigned from, unsigned to); /* * reiserfs_unpack * Function try to convert tail from direct item into indirect. * It set up nopack attribute in the REISERFS_I(inode)->nopack */ int reiserfs_unpack(struct inode *inode, struct file *filp) { int retval = 0; int index; struct page *page; struct address_space *mapping; unsigned long write_from; unsigned long blocksize = inode->i_sb->s_blocksize; if (inode->i_size == 0) { REISERFS_I(inode)->i_flags |= i_nopack_mask; return 0; } /* ioctl already done */ if (REISERFS_I(inode)->i_flags & i_nopack_mask) { return 0; } /* we need to make sure nobody is changing the file size beneath us */ { int depth = reiserfs_write_unlock_nested(inode->i_sb); inode_lock(inode); reiserfs_write_lock_nested(inode->i_sb, depth); } reiserfs_write_lock(inode->i_sb); write_from = inode->i_size & (blocksize - 1); /* if we are on a block boundary, we are already unpacked. */ if (write_from == 0) { REISERFS_I(inode)->i_flags |= i_nopack_mask; goto out; } /* * we unpack by finding the page with the tail, and calling * __reiserfs_write_begin on that page. This will force a * reiserfs_get_block to unpack the tail for us. */ index = inode->i_size >> PAGE_SHIFT; mapping = inode->i_mapping; page = grab_cache_page(mapping, index); retval = -ENOMEM; if (!page) { goto out; } retval = __reiserfs_write_begin(page, write_from, 0); if (retval) goto out_unlock; /* conversion can change page contents, must flush */ flush_dcache_page(page); retval = reiserfs_commit_write(NULL, page, write_from, write_from); REISERFS_I(inode)->i_flags |= i_nopack_mask; out_unlock: unlock_page(page); put_page(page); out: inode_unlock(inode); reiserfs_write_unlock(inode->i_sb); return retval; } /td>2017-01-30 11:41:25 +0100 commita76a82a3e38c8d3fb6499e3dfaeb0949241ab588 (patch) treeb5bc906278fe1ac66d75de984d26bf59b43b3ed8 /tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c parent566cf877a1fcb6d6dc0126b076aad062054c2637 (diff)
perf/core: Fix use-after-free bug
Dmitry reported a KASAN use-after-free on event->group_leader. It turns out there's a hole in perf_remove_from_context() due to event_function_call() not calling its function when the task associated with the event is already dead. In this case the event will have been detached from the task, but the grouping will have been retained, such that group operations might still work properly while there are live child events etc. This does however mean that we can miss a perf_group_detach() call when the group decomposes, this in turn can then lead to use-after-free. Fix it by explicitly doing the group detach if its still required. Reported-by: Dmitry Vyukov <dvyukov@google.com> Tested-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: stable@vger.kernel.org # v4.5+ Cc: syzkaller <syzkaller@googlegroups.com> Fixes: 63b6da39bb38 ("perf: Fix perf_event_exit_task() race") Link: http://lkml.kernel.org/r/20170126153955.GD6515@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/testing/selftests/powerpc/primitives/load_unaligned_zeropad.c')