Index: sys/kern/kern_sig.c =================================================================== --- sys/kern/kern_sig.c (wersja 244352) +++ sys/kern/kern_sig.c (kopia robocza) @@ -106,7 +106,6 @@ SDT_PROBE_ARGTYPE(proc, kernel, , signal_discard, 2, "int"); static int coredump(struct thread *); -static char *expand_name(const char *, uid_t, pid_t, struct thread *, int); static int killpg1(struct thread *td, int sig, int pgid, int all, ksiginfo_t *ksi); static int issignal(struct thread *td, int stop_allowed); @@ -3034,8 +3033,9 @@ sizeof(corefilename), "process corefile name format string"); /* - * expand_name(name, uid, pid, td, compress) - * Expand the name described in corefilename, using name, uid, and pid. + * corefile_open(comm, uid, pid, td, compress, vpp, namep) + * Expand the name described in corefilename, using name, uid, and pid + * and open/create core file. * corefilename is a printf-like string, with three format specifiers: * %N name of process ("name") * %P process id (pid) @@ -3044,22 +3044,21 @@ * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P". * This is controlled by the sysctl variable kern.corefile (see above). */ -static char * -expand_name(const char *comm, uid_t uid, pid_t pid, struct thread *td, - int compress) +static int +corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td, + int compress, struct vnode **vpp, char **namep) { + struct nameidata nd; struct sbuf sb; const char *format; - char *name; - size_t i; - int indexpos; - char *hostname; + char *hostname, *name; + int indexpos, i, error, cmode, flags, oflags; hostname = NULL; format = corefilename; name = malloc(MAXPATHLEN, M_TEMP, M_NOWAIT | M_ZERO); if (name == NULL) - return (NULL); + return (ENOMEM); indexpos = -1; (void)sbuf_new(&sb, name, MAXPATHLEN, SBUF_FIXEDLEN); for (i = 0; format[i]; i++) { @@ -3122,11 +3121,14 @@ nomem: sbuf_delete(&sb); free(name, M_TEMP); - return (NULL); + return (ENOMEM); } sbuf_finish(&sb); sbuf_delete(&sb); + cmode = S_IRUSR | S_IWUSR; + oflags = VN_OPEN_NOAUDIT | (capmode_coredump ? VN_OPEN_NOCAPCHECK : 0); + /* * If the core format has a %I in it, then we need to check * for existing corefiles before returning a name. @@ -3134,19 +3136,11 @@ * non-existing core file name to use. */ if (indexpos != -1) { - struct nameidata nd; - int error, n; - int flags = O_CREAT | O_EXCL | FWRITE | O_NOFOLLOW; - int cmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; - int oflags = 0; + flags = O_CREAT | O_EXCL | FWRITE | O_NOFOLLOW; - if (capmode_coredump) - oflags = VN_OPEN_NOCAPCHECK; - - for (n = 0; n < num_cores; n++) { - name[indexpos] = '0' + n; - NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, - name, td); + for (i = 0; i < num_cores; i++) { + name[indexpos] = '0' + i; + NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td); error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred, NULL); if (error) { @@ -3156,25 +3150,27 @@ "pid %d (%s), uid (%u): Path `%s' failed " "on initial open test, error = %d\n", pid, comm, uid, name, error); - free(name, M_TEMP); - return (NULL); } - NDFREE(&nd, NDF_ONLY_PNBUF); - VOP_UNLOCK(nd.ni_vp, 0); - error = vn_close(nd.ni_vp, FWRITE, td->td_ucred, td); - if (error) { - log(LOG_ERR, - "pid %d (%s), uid (%u): Path `%s' failed " - "on close after initial open test, " - "error = %d\n", - pid, comm, uid, name, error); - free(name, M_TEMP); - return (NULL); - } - break; + goto out; } } - return (name); + + flags = O_CREAT | FWRITE | O_NOFOLLOW; + + NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td); + error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred, NULL); +out: + if (error) { +#ifdef AUDIT + audit_proc_coredump(td, name, error); +#endif + free(name, M_TEMP); + return (error); + } + NDFREE(&nd, NDF_ONLY_PNBUF); + *vpp = nd.ni_vp; + *namep = name; + return (0); } /* @@ -3192,9 +3188,8 @@ struct ucred *cred = td->td_ucred; struct vnode *vp; struct flock lf; - struct nameidata nd; struct vattr vattr; - int error, error1, flags, locked; + int error, error1, locked; struct mount *mp; char *name; /* name of corefile */ off_t limit; @@ -3229,25 +3224,11 @@ } PROC_UNLOCK(p); - name = expand_name(p->p_comm, cred->cr_uid, p->p_pid, td, compress); - if (name == NULL) - return (EINVAL); - restart: - NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td); - flags = O_CREAT | FWRITE | O_NOFOLLOW; - error = vn_open_cred(&nd, &flags, S_IRUSR | S_IWUSR, - VN_OPEN_NOAUDIT | (capmode_coredump ? VN_OPEN_NOCAPCHECK : 0), - cred, NULL); - if (error) { -#ifdef AUDIT - audit_proc_coredump(td, name, error); -#endif - free(name, M_TEMP); + error = corefile_open(p->p_comm, cred->cr_uid, p->p_pid, td, compress, + &vp, &name); + if (error != 0) return (error); - } - NDFREE(&nd, NDF_ONLY_PNBUF); - 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) != 0 ||