You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs updates from Al Viro: "All kinds of stuff this time around; some more notable parts: - RCU'd vfsmounts handling - new primitives for coredump handling - files_lock is gone - Bruce's delegations handling series - exportfs fixes plus misc stuff all over the place" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (101 commits) ecryptfs: ->f_op is never NULL locks: break delegations on any attribute modification locks: break delegations on link locks: break delegations on rename locks: helper functions for delegation breaking locks: break delegations on unlink namei: minor vfs_unlink cleanup locks: implement delegations locks: introduce new FL_DELEG lock flag vfs: take i_mutex on renamed file vfs: rename I_MUTEX_QUOTA now that it's not used for quotas vfs: don't use PARENT/CHILD lock classes for non-directories vfs: pull ext4's double-i_mutex-locking into common code exportfs: fix quadratic behavior in filehandle lookup exportfs: better variable name exportfs: move most of reconnect_path to helper function exportfs: eliminate unused "noprogress" counter exportfs: stop retrying once we race with rename/remove exportfs: clear DISCONNECTED on all parents sooner exportfs: more detailed comment for path_reconnect ...
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
kinds of locks - per-inode (->i_mutex) and per-filesystem
|
||||
(->s_vfs_rename_mutex).
|
||||
|
||||
When taking the i_mutex on multiple non-directory objects, we
|
||||
always acquire the locks in order by increasing address. We'll call
|
||||
that "inode pointer" order in the following.
|
||||
|
||||
For our purposes all operations fall in 5 classes:
|
||||
|
||||
1) read access. Locking rules: caller locks directory we are accessing.
|
||||
@@ -12,8 +16,9 @@ kinds of locks - per-inode (->i_mutex) and per-filesystem
|
||||
locks victim and calls the method.
|
||||
|
||||
4) rename() that is _not_ cross-directory. Locking rules: caller locks
|
||||
the parent, finds source and target, if target already exists - locks it
|
||||
and then calls the method.
|
||||
the parent and finds source and target. If target already exists, lock
|
||||
it. If source is a non-directory, lock it. If that means we need to
|
||||
lock both, lock them in inode pointer order.
|
||||
|
||||
5) link creation. Locking rules:
|
||||
* lock parent
|
||||
@@ -30,7 +35,9 @@ rules:
|
||||
fail with -ENOTEMPTY
|
||||
* if new parent is equal to or is a descendent of source
|
||||
fail with -ELOOP
|
||||
* if target exists - lock it.
|
||||
* If target exists, lock it. If source is a non-directory, lock
|
||||
it. In case that means we need to lock both source and target,
|
||||
do so in inode pointer order.
|
||||
* call the method.
|
||||
|
||||
|
||||
@@ -56,9 +63,11 @@ objects - A < B iff A is an ancestor of B.
|
||||
renames will be blocked on filesystem lock and we don't start changing
|
||||
the order until we had acquired all locks).
|
||||
|
||||
(3) any operation holds at most one lock on non-directory object and
|
||||
that lock is acquired after all other locks. (Proof: see descriptions
|
||||
of operations).
|
||||
(3) locks on non-directory objects are acquired only after locks on
|
||||
directory objects, and are acquired in inode pointer order.
|
||||
(Proof: all operations but renames take lock on at most one
|
||||
non-directory object, except renames, which take locks on source and
|
||||
target in inode pointer order in the case they are not directories.)
|
||||
|
||||
Now consider the minimal deadlock. Each process is blocked on
|
||||
attempt to acquire some lock and already holds at least one lock. Let's
|
||||
@@ -66,9 +75,13 @@ consider the set of contended locks. First of all, filesystem lock is
|
||||
not contended, since any process blocked on it is not holding any locks.
|
||||
Thus all processes are blocked on ->i_mutex.
|
||||
|
||||
Non-directory objects are not contended due to (3). Thus link
|
||||
creation can't be a part of deadlock - it can't be blocked on source
|
||||
and it means that it doesn't hold any locks.
|
||||
By (3), any process holding a non-directory lock can only be
|
||||
waiting on another non-directory lock with a larger address. Therefore
|
||||
the process holding the "largest" such lock can always make progress, and
|
||||
non-directory objects are not included in the set of contended locks.
|
||||
|
||||
Thus link creation can't be a part of deadlock - it can't be
|
||||
blocked on source and it means that it doesn't hold any locks.
|
||||
|
||||
Any contended object is either held by cross-directory rename or
|
||||
has a child that is also contended. Indeed, suppose that it is held by
|
||||
|
||||
@@ -455,3 +455,11 @@ in your dentry operations instead.
|
||||
vfs_follow_link has been removed. Filesystems must use nd_set_link
|
||||
from ->follow_link for normal symlinks, or nd_jump_link for magic
|
||||
/proc/<pid> style links.
|
||||
--
|
||||
[mandatory]
|
||||
iget5_locked()/ilookup5()/ilookup5_nowait() test() callback used to be
|
||||
called with both ->i_lock and inode_hash_lock held; the former is *not*
|
||||
taken anymore, so verify that your callbacks do not rely on it (none
|
||||
of the in-tree instances did). inode_hash_lock is still held,
|
||||
of course, so they are still serialized wrt removal from inode hash,
|
||||
as well as wrt set() callback of iget5_locked().
|
||||
|
||||
@@ -122,7 +122,7 @@ static inline int get_sigset_t(sigset_t *set,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
||||
@@ -11,8 +11,7 @@ Elf64_Half elf_core_extra_phdrs(void)
|
||||
return GATE_EHDR->e_phnum;
|
||||
}
|
||||
|
||||
int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
|
||||
unsigned long limit)
|
||||
int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)
|
||||
{
|
||||
const struct elf_phdr *const gate_phdrs =
|
||||
(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
|
||||
@@ -35,15 +34,13 @@ int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
|
||||
phdr.p_offset += ofs;
|
||||
}
|
||||
phdr.p_paddr = 0; /* match other core phdrs */
|
||||
*size += sizeof(phdr);
|
||||
if (*size > limit || !dump_write(file, &phdr, sizeof(phdr)))
|
||||
if (!dump_emit(cprm, &phdr, sizeof(phdr)))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int elf_core_write_extra_data(struct file *file, size_t *size,
|
||||
unsigned long limit)
|
||||
int elf_core_write_extra_data(struct coredump_params *cprm)
|
||||
{
|
||||
const struct elf_phdr *const gate_phdrs =
|
||||
(const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
|
||||
@@ -54,8 +51,7 @@ int elf_core_write_extra_data(struct file *file, size_t *size,
|
||||
void *addr = (void *)gate_phdrs[i].p_vaddr;
|
||||
size_t memsz = PAGE_ALIGN(gate_phdrs[i].p_memsz);
|
||||
|
||||
*size += memsz;
|
||||
if (*size > limit || !dump_write(file, addr, memsz))
|
||||
if (!dump_emit(cprm, addr, memsz))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr)
|
||||
}
|
||||
|
||||
int
|
||||
copy_siginfo_to_user (siginfo_t __user *to, siginfo_t *from)
|
||||
copy_siginfo_to_user (siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t)))
|
||||
return -EFAULT;
|
||||
|
||||
@@ -314,7 +314,7 @@ SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
||||
@@ -319,7 +319,7 @@ copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
|
||||
}
|
||||
|
||||
int
|
||||
copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
|
||||
copy_siginfo_to_user32 (compat_siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
compat_uptr_t addr;
|
||||
compat_int_t val;
|
||||
|
||||
@@ -34,7 +34,7 @@ struct compat_ucontext {
|
||||
|
||||
/* ELF32 signal handling */
|
||||
|
||||
int copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from);
|
||||
int copy_siginfo_to_user32 (compat_siginfo_t __user *to, const siginfo_t *from);
|
||||
int copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from);
|
||||
|
||||
/* In a deft move of uber-hackery, we decide to carry the top half of all
|
||||
|
||||
@@ -235,6 +235,7 @@ extern long spu_sys_callback(struct spu_syscall_block *s);
|
||||
|
||||
/* syscalls implemented in spufs */
|
||||
struct file;
|
||||
struct coredump_params;
|
||||
struct spufs_calls {
|
||||
long (*create_thread)(const char __user *name,
|
||||
unsigned int flags, umode_t mode,
|
||||
@@ -242,7 +243,7 @@ struct spufs_calls {
|
||||
long (*spu_run)(struct file *filp, __u32 __user *unpc,
|
||||
__u32 __user *ustatus);
|
||||
int (*coredump_extra_notes_size)(void);
|
||||
int (*coredump_extra_notes_write)(struct file *file, loff_t *foffset);
|
||||
int (*coredump_extra_notes_write)(struct coredump_params *cprm);
|
||||
void (*notify_spus_active)(void);
|
||||
struct module *owner;
|
||||
};
|
||||
|
||||
@@ -893,7 +893,7 @@ static long restore_tm_user_regs(struct pt_regs *regs,
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s)
|
||||
int copy_siginfo_to_user32(struct compat_siginfo __user *d, const siginfo_t *s)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/binfmts.h>
|
||||
|
||||
#include <asm/spu.h>
|
||||
|
||||
@@ -126,7 +127,7 @@ int elf_coredump_extra_notes_size(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset)
|
||||
int elf_coredump_extra_notes_write(struct coredump_params *cprm)
|
||||
{
|
||||
struct spufs_calls *calls;
|
||||
int ret;
|
||||
@@ -135,7 +136,7 @@ int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset)
|
||||
if (!calls)
|
||||
return 0;
|
||||
|
||||
ret = calls->coredump_extra_notes_write(file, foffset);
|
||||
ret = calls->coredump_extra_notes_write(cprm);
|
||||
|
||||
spufs_calls_put(calls);
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/coredump.h>
|
||||
#include <linux/binfmts.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
@@ -48,44 +50,6 @@ static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,
|
||||
return ++ret; /* count trailing NULL */
|
||||
}
|
||||
|
||||
/*
|
||||
* These are the only things you should do on a core-file: use only these
|
||||
* functions to write out all the necessary info.
|
||||
*/
|
||||
static int spufs_dump_write(struct file *file, const void *addr, int nr, loff_t *foffset)
|
||||
{
|
||||
unsigned long limit = rlimit(RLIMIT_CORE);
|
||||
ssize_t written;
|
||||
|
||||
if (*foffset + nr > limit)
|
||||
return -EIO;
|
||||
|
||||
written = file->f_op->write(file, addr, nr, &file->f_pos);
|
||||
*foffset += written;
|
||||
|
||||
if (written != nr)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spufs_dump_align(struct file *file, char *buf, loff_t new_off,
|
||||
loff_t *foffset)
|
||||
{
|
||||
int rc, size;
|
||||
|
||||
size = min((loff_t)PAGE_SIZE, new_off - *foffset);
|
||||
memset(buf, 0, size);
|
||||
|
||||
rc = 0;
|
||||
while (rc == 0 && new_off > *foffset) {
|
||||
size = min((loff_t)PAGE_SIZE, new_off - *foffset);
|
||||
rc = spufs_dump_write(file, buf, size, foffset);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
|
||||
{
|
||||
int i, sz, total = 0;
|
||||
@@ -165,10 +129,10 @@ int spufs_coredump_extra_notes_size(void)
|
||||
}
|
||||
|
||||
static int spufs_arch_write_note(struct spu_context *ctx, int i,
|
||||
struct file *file, int dfd, loff_t *foffset)
|
||||
struct coredump_params *cprm, int dfd)
|
||||
{
|
||||
loff_t pos = 0;
|
||||
int sz, rc, nread, total = 0;
|
||||
int sz, rc, total = 0;
|
||||
const int bufsz = PAGE_SIZE;
|
||||
char *name;
|
||||
char fullname[80], *buf;
|
||||
@@ -186,42 +150,39 @@ static int spufs_arch_write_note(struct spu_context *ctx, int i,
|
||||
en.n_descsz = sz;
|
||||
en.n_type = NT_SPU;
|
||||
|
||||
rc = spufs_dump_write(file, &en, sizeof(en), foffset);
|
||||
if (rc)
|
||||
goto out;
|
||||
if (!dump_emit(cprm, &en, sizeof(en)))
|
||||
goto Eio;
|
||||
|
||||
rc = spufs_dump_write(file, fullname, en.n_namesz, foffset);
|
||||
if (rc)
|
||||
goto out;
|
||||
if (!dump_emit(cprm, fullname, en.n_namesz))
|
||||
goto Eio;
|
||||
|
||||
rc = spufs_dump_align(file, buf, roundup(*foffset, 4), foffset);
|
||||
if (rc)
|
||||
goto out;
|
||||
if (!dump_align(cprm, 4))
|
||||
goto Eio;
|
||||
|
||||
do {
|
||||
nread = do_coredump_read(i, ctx, buf, bufsz, &pos);
|
||||
if (nread > 0) {
|
||||
rc = spufs_dump_write(file, buf, nread, foffset);
|
||||
if (rc)
|
||||
goto out;
|
||||
total += nread;
|
||||
rc = do_coredump_read(i, ctx, buf, bufsz, &pos);
|
||||
if (rc > 0) {
|
||||
if (!dump_emit(cprm, buf, rc))
|
||||
goto Eio;
|
||||
total += rc;
|
||||
}
|
||||
} while (nread == bufsz && total < sz);
|
||||
} while (rc == bufsz && total < sz);
|
||||
|
||||
if (nread < 0) {
|
||||
rc = nread;
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = spufs_dump_align(file, buf, roundup(*foffset - total + sz, 4),
|
||||
foffset);
|
||||
|
||||
if (!dump_skip(cprm,
|
||||
roundup(cprm->written - total + sz, 4) - cprm->written))
|
||||
goto Eio;
|
||||
out:
|
||||
free_page((unsigned long)buf);
|
||||
return rc;
|
||||
Eio:
|
||||
free_page((unsigned long)buf);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset)
|
||||
int spufs_coredump_extra_notes_write(struct coredump_params *cprm)
|
||||
{
|
||||
struct spu_context *ctx;
|
||||
int fd, j, rc;
|
||||
@@ -233,7 +194,7 @@ int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset)
|
||||
return rc;
|
||||
|
||||
for (j = 0; spufs_coredump_read[j].name != NULL; j++) {
|
||||
rc = spufs_arch_write_note(ctx, j, file, fd, foffset);
|
||||
rc = spufs_arch_write_note(ctx, j, cprm, fd);
|
||||
if (rc) {
|
||||
spu_release_saved(ctx);
|
||||
return rc;
|
||||
|
||||
@@ -247,12 +247,13 @@ extern const struct spufs_tree_descr spufs_dir_debug_contents[];
|
||||
|
||||
/* system call implementation */
|
||||
extern struct spufs_calls spufs_calls;
|
||||
struct coredump_params;
|
||||
long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status);
|
||||
long spufs_create(struct path *nd, struct dentry *dentry, unsigned int flags,
|
||||
umode_t mode, struct file *filp);
|
||||
/* ELF coredump callbacks for writing SPU ELF notes */
|
||||
extern int spufs_coredump_extra_notes_size(void);
|
||||
extern int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset);
|
||||
extern int spufs_coredump_extra_notes_write(struct coredump_params *cprm);
|
||||
|
||||
extern const struct file_operations spufs_context_fops;
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ typedef struct
|
||||
__u32 gprs_high[NUM_GPRS];
|
||||
} rt_sigframe32;
|
||||
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ struct rt_signal_frame32 {
|
||||
/* __siginfo_rwin_t * */u32 rwin_save;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ struct compat_rt_sigframe {
|
||||
struct compat_ucontext uc;
|
||||
};
|
||||
|
||||
int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from)
|
||||
int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *from)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
||||
+42
-44
@@ -25,6 +25,7 @@
|
||||
#include <linux/personality.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/perf_event.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/pgalloc.h>
|
||||
@@ -33,14 +34,18 @@
|
||||
#include <asm/ia32.h>
|
||||
|
||||
#undef WARN_OLD
|
||||
#undef CORE_DUMP /* definitely broken */
|
||||
|
||||
static int load_aout_binary(struct linux_binprm *);
|
||||
static int load_aout_library(struct file *);
|
||||
|
||||
#ifdef CORE_DUMP
|
||||
static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file,
|
||||
unsigned long limit);
|
||||
#ifdef CONFIG_COREDUMP
|
||||
static int aout_core_dump(struct coredump_params *);
|
||||
|
||||
static unsigned long get_dr(int n)
|
||||
{
|
||||
struct perf_event *bp = current->thread.ptrace_bps[n];
|
||||
return bp ? bp->hw.info.address : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* fill in the user structure for a core dump..
|
||||
@@ -48,6 +53,7 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file,
|
||||
static void dump_thread32(struct pt_regs *regs, struct user32 *dump)
|
||||
{
|
||||
u32 fs, gs;
|
||||
memset(dump, 0, sizeof(*dump));
|
||||
|
||||
/* changed the size calculations - should hopefully work better. lbt */
|
||||
dump->magic = CMAGIC;
|
||||
@@ -57,15 +63,12 @@ static void dump_thread32(struct pt_regs *regs, struct user32 *dump)
|
||||
dump->u_dsize = ((unsigned long)
|
||||
(current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
|
||||
dump->u_dsize -= dump->u_tsize;
|
||||
dump->u_ssize = 0;
|
||||
dump->u_debugreg[0] = current->thread.debugreg0;
|
||||
dump->u_debugreg[1] = current->thread.debugreg1;
|
||||
dump->u_debugreg[2] = current->thread.debugreg2;
|
||||
dump->u_debugreg[3] = current->thread.debugreg3;
|
||||
dump->u_debugreg[4] = 0;
|
||||
dump->u_debugreg[5] = 0;
|
||||
dump->u_debugreg[0] = get_dr(0);
|
||||
dump->u_debugreg[1] = get_dr(1);
|
||||
dump->u_debugreg[2] = get_dr(2);
|
||||
dump->u_debugreg[3] = get_dr(3);
|
||||
dump->u_debugreg[6] = current->thread.debugreg6;
|
||||
dump->u_debugreg[7] = current->thread.debugreg7;
|
||||
dump->u_debugreg[7] = current->thread.ptrace_dr7;
|
||||
|
||||
if (dump->start_stack < 0xc0000000) {
|
||||
unsigned long tmp;
|
||||
@@ -74,24 +77,24 @@ static void dump_thread32(struct pt_regs *regs, struct user32 *dump)
|
||||
dump->u_ssize = tmp >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
dump->regs.bx = regs->bx;
|
||||
dump->regs.cx = regs->cx;
|
||||
dump->regs.dx = regs->dx;
|
||||
dump->regs.si = regs->si;
|
||||
dump->regs.di = regs->di;
|
||||
dump->regs.bp = regs->bp;
|
||||
dump->regs.ax = regs->ax;
|
||||
dump->regs.ebx = regs->bx;
|
||||
dump->regs.ecx = regs->cx;
|
||||
dump->regs.edx = regs->dx;
|
||||
dump->regs.esi = regs->si;
|
||||
dump->regs.edi = regs->di;
|
||||
dump->regs.ebp = regs->bp;
|
||||
dump->regs.eax = regs->ax;
|
||||
dump->regs.ds = current->thread.ds;
|
||||
dump->regs.es = current->thread.es;
|
||||
savesegment(fs, fs);
|
||||
dump->regs.fs = fs;
|
||||
savesegment(gs, gs);
|
||||
dump->regs.gs = gs;
|
||||
dump->regs.orig_ax = regs->orig_ax;
|
||||
dump->regs.ip = regs->ip;
|
||||
dump->regs.orig_eax = regs->orig_ax;
|
||||
dump->regs.eip = regs->ip;
|
||||
dump->regs.cs = regs->cs;
|
||||
dump->regs.flags = regs->flags;
|
||||
dump->regs.sp = regs->sp;
|
||||
dump->regs.eflags = regs->flags;
|
||||
dump->regs.esp = regs->sp;
|
||||
dump->regs.ss = regs->ss;
|
||||
|
||||
#if 1 /* FIXME */
|
||||
@@ -107,7 +110,7 @@ static struct linux_binfmt aout_format = {
|
||||
.module = THIS_MODULE,
|
||||
.load_binary = load_aout_binary,
|
||||
.load_shlib = load_aout_library,
|
||||
#ifdef CORE_DUMP
|
||||
#ifdef CONFIG_COREDUMP
|
||||
.core_dump = aout_core_dump,
|
||||
#endif
|
||||
.min_coredump = PAGE_SIZE
|
||||
@@ -122,7 +125,7 @@ static void set_brk(unsigned long start, unsigned long end)
|
||||
vm_brk(start, end - start);
|
||||
}
|
||||
|
||||
#ifdef CORE_DUMP
|
||||
#ifdef CONFIG_COREDUMP
|
||||
/*
|
||||
* These are the only things you should do on a core-file: use only these
|
||||
* macros to write out all the necessary info.
|
||||
@@ -130,15 +133,7 @@ static void set_brk(unsigned long start, unsigned long end)
|
||||
|
||||
#include <linux/coredump.h>
|
||||
|
||||
#define DUMP_WRITE(addr, nr) \
|
||||
if (!dump_write(file, (void *)(addr), (nr))) \
|
||||
goto end_coredump;
|
||||
|
||||
#define DUMP_SEEK(offset) \
|
||||
if (!dump_seek(file, offset)) \
|
||||
goto end_coredump;
|
||||
|
||||
#define START_DATA() (u.u_tsize << PAGE_SHIFT)
|
||||
#define START_DATA(u) (u.u_tsize << PAGE_SHIFT)
|
||||
#define START_STACK(u) (u.start_stack)
|
||||
|
||||
/*
|
||||
@@ -151,8 +146,7 @@ static void set_brk(unsigned long start, unsigned long end)
|
||||
* dumping of the process results in another error..
|
||||
*/
|
||||
|
||||
static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file,
|
||||
unsigned long limit)
|
||||
static int aout_core_dump(struct coredump_params *cprm)
|
||||
{
|
||||
mm_segment_t fs;
|
||||
int has_dumped = 0;
|
||||
@@ -164,19 +158,19 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file,
|
||||
has_dumped = 1;
|
||||
strncpy(dump.u_comm, current->comm, sizeof(current->comm));
|
||||
dump.u_ar0 = offsetof(struct user32, regs);
|
||||
dump.signal = signr;
|
||||
dump_thread32(regs, &dump);
|
||||
dump.signal = cprm->siginfo->si_signo;
|
||||
dump_thread32(cprm->regs, &dump);
|
||||
|
||||
/*
|
||||
* If the size of the dump file exceeds the rlimit, then see
|
||||
* what would happen if we wrote the stack, but not the data
|
||||
* area.
|
||||
*/
|
||||
if ((dump.u_dsize + dump.u_ssize + 1) * PAGE_SIZE > limit)
|
||||
if ((dump.u_dsize + dump.u_ssize + 1) * PAGE_SIZE > cprm->limit)
|
||||
dump.u_dsize = 0;
|
||||
|
||||
/* Make sure we have enough room to write the stack and data areas. */
|
||||
if ((dump.u_ssize + 1) * PAGE_SIZE > limit)
|
||||
if ((dump.u_ssize + 1) * PAGE_SIZE > cprm->limit)
|
||||
dump.u_ssize = 0;
|
||||
|
||||
/* make sure we actually have a data and stack area to dump */
|
||||
@@ -190,22 +184,26 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file,
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
/* struct user */
|
||||
DUMP_WRITE(&dump, sizeof(dump));
|
||||
if (!dump_emit(cprm, &dump, sizeof(dump)))
|
||||
goto end_coredump;
|
||||
/* Now dump all of the user data. Include malloced stuff as well */
|
||||
DUMP_SEEK(PAGE_SIZE - sizeof(dump));
|
||||
if (!dump_skip(cprm, PAGE_SIZE - sizeof(dump)))
|
||||
goto end_coredump;
|
||||
/* now we start writing out the user space info */
|
||||
set_fs(USER_DS);
|
||||
/* Dump the data area */
|
||||
if (dump.u_dsize != 0) {
|
||||
dump_start = START_DATA(dump);
|
||||
dump_size = dump.u_dsize << PAGE_SHIFT;
|
||||
DUMP_WRITE(dump_start, dump_size);
|
||||
if (!dump_emit(cprm, (void *)dump_start, dump_size))
|
||||
goto end_coredump;
|
||||
}
|
||||
/* Now prepare to dump the stack area */
|
||||
if (dump.u_ssize != 0) {
|
||||
dump_start = START_STACK(dump);
|
||||
dump_size = dump.u_ssize << PAGE_SHIFT;
|
||||
DUMP_WRITE(dump_start, dump_size);
|
||||
if (!dump_emit(cprm, (void *)dump_start, dump_size))
|
||||
goto end_coredump;
|
||||
}
|
||||
end_coredump:
|
||||
set_fs(fs);
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <asm/sys_ia32.h>
|
||||
#include <asm/smap.h>
|
||||
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
int err = 0;
|
||||
bool ia32 = test_thread_flag(TIF_IA32);
|
||||
|
||||
+4
-11
@@ -11,8 +11,7 @@ Elf32_Half elf_core_extra_phdrs(void)
|
||||
return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0;
|
||||
}
|
||||
|
||||
int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
|
||||
unsigned long limit)
|
||||
int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset)
|
||||
{
|
||||
if ( vsyscall_ehdr ) {
|
||||
const struct elfhdr *const ehdrp =
|
||||
@@ -32,17 +31,14 @@ int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
|
||||
phdr.p_offset += ofs;
|
||||
}
|
||||
phdr.p_paddr = 0; /* match other core phdrs */
|
||||
*size += sizeof(phdr);
|
||||
if (*size > limit
|
||||
|| !dump_write(file, &phdr, sizeof(phdr)))
|
||||
if (!dump_emit(cprm, &phdr, sizeof(phdr)))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int elf_core_write_extra_data(struct file *file, size_t *size,
|
||||
unsigned long limit)
|
||||
int elf_core_write_extra_data(struct coredump_params *cprm)
|
||||
{
|
||||
if ( vsyscall_ehdr ) {
|
||||
const struct elfhdr *const ehdrp =
|
||||
@@ -55,10 +51,7 @@ int elf_core_write_extra_data(struct file *file, size_t *size,
|
||||
if (phdrp[i].p_type == PT_LOAD) {
|
||||
void *addr = (void *) phdrp[i].p_vaddr;
|
||||
size_t filesz = phdrp[i].p_filesz;
|
||||
|
||||
*size += filesz;
|
||||
if (*size > limit
|
||||
|| !dump_write(file, addr, filesz))
|
||||
if (!dump_emit(cprm, addr, filesz))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@ static int handle_create(const char *nodename, umode_t mode, kuid_t uid,
|
||||
newattrs.ia_gid = gid;
|
||||
newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID;
|
||||
mutex_lock(&dentry->d_inode->i_mutex);
|
||||
notify_change(dentry, &newattrs);
|
||||
notify_change(dentry, &newattrs, NULL);
|
||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||
|
||||
/* mark as kernel-created inode */
|
||||
@@ -322,9 +322,9 @@ static int handle_remove(const char *nodename, struct device *dev)
|
||||
newattrs.ia_valid =
|
||||
ATTR_UID|ATTR_GID|ATTR_MODE;
|
||||
mutex_lock(&dentry->d_inode->i_mutex);
|
||||
notify_change(dentry, &newattrs);
|
||||
notify_change(dentry, &newattrs, NULL);
|
||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||
err = vfs_unlink(parent.dentry->d_inode, dentry);
|
||||
err = vfs_unlink(parent.dentry->d_inode, dentry, NULL);
|
||||
if (!err || err == -ENOENT)
|
||||
deleted = 1;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user