39c39
< * $FreeBSD: head/sys/kern/kern_sig.c 50477 1999-08-28 01:08:13Z peter $
---
> * $FreeBSD: head/sys/kern/kern_sig.c 50717 1999-09-01 00:29:56Z julian $
73a74,75
> static char *expand_name __P((const char *, uid_t, int));
> static int coredump __P((struct proc *));
1258,1259c1260
< if (p->p_sysent->sv_coredump != NULL &&
< (*p->p_sysent->sv_coredump)(p) == 0)
---
> if (coredump(p) == 0)
1289c1290
< char *
---
> static char *
1355a1357,1421
> * Dump a process' core. The main routine does some
> * policy checking, and creates the name of the coredump;
> * then it passes on a vnode and a size limit to the process-specific
> * coredump routine if there is one; if there _is not_ one, it returns
> * ENOSYS; otherwise it returns the error from the process-specific routine.
> */
>
> static int
> coredump(p)
> register struct proc *p;
> {
> register struct vnode *vp;
> register struct ucred *cred = p->p_cred->pc_ucred;
> struct nameidata nd;
> struct vattr vattr;
> int error, error1;
> char *name; /* name of corefile */
> off_t limit;
>
> STOPEVENT(p, S_CORE, 0);
>
> if ((sugid_coredump == 0) && p->p_flag & P_SUGID)
> return (EFAULT);
>
> /*
> * Note that this layout means that limit checking is done
> * AFTER the corefile name is created. This could happen
> * other ways as well, so I'm not too worried about it, but
> * it is potentially confusing.
> */
> name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
> NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
> error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR);
> free(name, M_TEMP);
> if (error)
> return (error);
> vp = nd.ni_vp;
>
> /* Don't dump to non-regular files or files with links. */
> if (vp->v_type != VREG ||
> VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) {
> error = EFAULT;
> goto out;
> }
> VATTR_NULL(&vattr);
> vattr.va_size = 0;
> VOP_LEASE(vp, p, cred, LEASE_WRITE);
> VOP_SETATTR(vp, &vattr, cred, p);
> p->p_acflag |= ACORE;
>
> limit = p->p_rlimit[RLIMIT_CORE].rlim_cur;
>
> error = p->p_sysent->sv_coredump ?
> p->p_sysent->sv_coredump(p, vp, limit) :
> ENOSYS;
>
> out:
> VOP_UNLOCK(vp, 0, p);
> error1 = vn_close(vp, FWRITE, cred, p);
> if (error == 0)
> error = error1;
> return (error);
> }
>
> /*
< * $FreeBSD: head/sys/kern/kern_sig.c 50477 1999-08-28 01:08:13Z peter $
---
> * $FreeBSD: head/sys/kern/kern_sig.c 50717 1999-09-01 00:29:56Z julian $
73a74,75
> static char *expand_name __P((const char *, uid_t, int));
> static int coredump __P((struct proc *));
1258,1259c1260
< if (p->p_sysent->sv_coredump != NULL &&
< (*p->p_sysent->sv_coredump)(p) == 0)
---
> if (coredump(p) == 0)
1289c1290
< char *
---
> static char *
1355a1357,1421
> * Dump a process' core. The main routine does some
> * policy checking, and creates the name of the coredump;
> * then it passes on a vnode and a size limit to the process-specific
> * coredump routine if there is one; if there _is not_ one, it returns
> * ENOSYS; otherwise it returns the error from the process-specific routine.
> */
>
> static int
> coredump(p)
> register struct proc *p;
> {
> register struct vnode *vp;
> register struct ucred *cred = p->p_cred->pc_ucred;
> struct nameidata nd;
> struct vattr vattr;
> int error, error1;
> char *name; /* name of corefile */
> off_t limit;
>
> STOPEVENT(p, S_CORE, 0);
>
> if ((sugid_coredump == 0) && p->p_flag & P_SUGID)
> return (EFAULT);
>
> /*
> * Note that this layout means that limit checking is done
> * AFTER the corefile name is created. This could happen
> * other ways as well, so I'm not too worried about it, but
> * it is potentially confusing.
> */
> name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
> NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
> error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR);
> free(name, M_TEMP);
> if (error)
> return (error);
> vp = nd.ni_vp;
>
> /* Don't dump to non-regular files or files with links. */
> if (vp->v_type != VREG ||
> VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) {
> error = EFAULT;
> goto out;
> }
> VATTR_NULL(&vattr);
> vattr.va_size = 0;
> VOP_LEASE(vp, p, cred, LEASE_WRITE);
> VOP_SETATTR(vp, &vattr, cred, p);
> p->p_acflag |= ACORE;
>
> limit = p->p_rlimit[RLIMIT_CORE].rlim_cur;
>
> error = p->p_sysent->sv_coredump ?
> p->p_sysent->sv_coredump(p, vp, limit) :
> ENOSYS;
>
> out:
> VOP_UNLOCK(vp, 0, p);
> error1 = vn_close(vp, FWRITE, cred, p);
> if (error == 0)
> error = error1;
> return (error);
> }
>
> /*