Fixes for i/o during coredumping:
- Do not dump into system files. - Do not acquire write reference to the mount point where img.core is written, in the coredump(). The vn_rdwr() calls from ELF imgact request the write ref from vn_rdwr(). Recursive acqusition of the write ref deadlocks with the unmount. - Instead, take the range lock for the whole core file. This prevents parallel dumping from two processes executing the same image, converting the useless interleaved dump into sequential dumping, with second core overwriting the first. Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks
This commit is contained in:
parent
e3d6feceb1
commit
539c9eef12
@ -1112,8 +1112,8 @@ core_output(struct vnode *vp, void *base, size_t len, off_t offset,
|
||||
#endif
|
||||
} else {
|
||||
error = vn_rdwr_inchunks(UIO_WRITE, vp, base, len, offset,
|
||||
UIO_USERSPACE, IO_UNIT | IO_DIRECT, active_cred, file_cred,
|
||||
NULL, td);
|
||||
UIO_USERSPACE, IO_UNIT | IO_DIRECT | IO_RANGELOCKED,
|
||||
active_cred, file_cred, NULL, td);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
@ -1160,8 +1160,8 @@ sbuf_drain_core_output(void *arg, const char *data, int len)
|
||||
#endif
|
||||
error = vn_rdwr_inchunks(UIO_WRITE, p->vp,
|
||||
__DECONST(void *, data), len, p->offset, UIO_SYSSPACE,
|
||||
IO_UNIT | IO_DIRECT, p->active_cred, p->file_cred, NULL,
|
||||
p->td);
|
||||
IO_UNIT | IO_DIRECT | IO_RANGELOCKED, p->active_cred,
|
||||
p->file_cred, NULL, p->td);
|
||||
if (locked)
|
||||
PROC_LOCK(p->td->td_proc);
|
||||
if (error != 0)
|
||||
|
@ -3214,8 +3214,8 @@ coredump(struct thread *td)
|
||||
struct flock lf;
|
||||
struct vattr vattr;
|
||||
int error, error1, locked;
|
||||
struct mount *mp;
|
||||
char *name; /* name of corefile */
|
||||
void *rl_cookie;
|
||||
off_t limit;
|
||||
int compress;
|
||||
|
||||
@ -3248,39 +3248,33 @@ coredump(struct thread *td)
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
restart:
|
||||
error = corefile_open(p->p_comm, cred->cr_uid, p->p_pid, td, compress,
|
||||
&vp, &name);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
/* Don't dump to non-regular files or files with links. */
|
||||
/*
|
||||
* Don't dump to non-regular files or files with links.
|
||||
* Do not dump into system files.
|
||||
*/
|
||||
if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred) != 0 ||
|
||||
vattr.va_nlink != 1) {
|
||||
vattr.va_nlink != 1 || (vp->v_vflag & VV_SYSTEM) != 0) {
|
||||
VOP_UNLOCK(vp, 0);
|
||||
error = EFAULT;
|
||||
goto close;
|
||||
}
|
||||
|
||||
VOP_UNLOCK(vp, 0);
|
||||
|
||||
/* Postpone other writers, including core dumps of other processes. */
|
||||
rl_cookie = vn_rangelock_wlock(vp, 0, OFF_MAX);
|
||||
|
||||
lf.l_whence = SEEK_SET;
|
||||
lf.l_start = 0;
|
||||
lf.l_len = 0;
|
||||
lf.l_type = F_WRLCK;
|
||||
locked = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &lf, F_FLOCK) == 0);
|
||||
|
||||
if (vn_start_write(vp, &mp, V_NOWAIT) != 0) {
|
||||
lf.l_type = F_UNLCK;
|
||||
if (locked)
|
||||
VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK);
|
||||
if ((error = vn_close(vp, FWRITE, cred, td)) != 0)
|
||||
goto out;
|
||||
if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
|
||||
goto out;
|
||||
free(name, M_TEMP);
|
||||
goto restart;
|
||||
}
|
||||
|
||||
VATTR_NULL(&vattr);
|
||||
vattr.va_size = 0;
|
||||
if (set_core_nodump_flag)
|
||||
@ -3288,7 +3282,6 @@ restart:
|
||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
|
||||
VOP_SETATTR(vp, &vattr, cred);
|
||||
VOP_UNLOCK(vp, 0);
|
||||
vn_finished_write(mp);
|
||||
PROC_LOCK(p);
|
||||
p->p_acflag |= ACORE;
|
||||
PROC_UNLOCK(p);
|
||||
@ -3304,11 +3297,11 @@ restart:
|
||||
lf.l_type = F_UNLCK;
|
||||
VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_FLOCK);
|
||||
}
|
||||
vn_rangelock_unlock(vp, rl_cookie);
|
||||
close:
|
||||
error1 = vn_close(vp, FWRITE, cred, td);
|
||||
if (error == 0)
|
||||
error = error1;
|
||||
out:
|
||||
#ifdef AUDIT
|
||||
audit_proc_coredump(td, name, error);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user