PR/35278: YAMAMOTO Takashi: veriexec sometimes feeds user va to log(9)
Introduce the (intentionally undocumented) pathname_get(), pathname_path(), and pathname_put(), to deal with allocating and copying of pathnames from either kernel- or user-space.
This commit is contained in:
parent
6e478b060b
commit
1124b0b8bc
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vfs_lookup.c,v 1.75 2006/12/13 13:36:19 yamt Exp $ */
|
||||
/* $NetBSD: vfs_lookup.c,v 1.76 2006/12/24 08:54:55 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.75 2006/12/13 13:36:19 yamt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.76 2006/12/24 08:54:55 elad Exp $");
|
||||
|
||||
#include "opt_ktrace.h"
|
||||
#include "opt_systrace.h"
|
||||
|
@ -70,6 +70,11 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.75 2006/12/13 13:36:19 yamt Exp $")
|
|||
#define MAGICLINKS 0
|
||||
#endif
|
||||
|
||||
struct pathname_internal {
|
||||
char *pathbuf;
|
||||
boolean_t needfree;
|
||||
};
|
||||
|
||||
int vfs_magiclinks = MAGICLINKS;
|
||||
|
||||
struct pool pnbuf_pool; /* pathname buffer pool */
|
||||
|
@ -191,6 +196,52 @@ symlink_magic(struct proc *p, char *cp, int *len)
|
|||
#undef MATCH
|
||||
#undef SUBSTITUTE
|
||||
|
||||
int
|
||||
pathname_get(const char *dirp, enum uio_seg segflg, pathname_t *path)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (dirp == NULL)
|
||||
return (EFAULT);
|
||||
|
||||
*path = malloc(sizeof(struct pathname_internal), M_TEMP,
|
||||
M_ZERO|M_WAITOK);
|
||||
|
||||
if (segflg == UIO_USERSPACE) {
|
||||
(*path)->pathbuf = PNBUF_GET();
|
||||
error = copyinstr(dirp, (*path)->pathbuf, MAXPATHLEN,
|
||||
NULL);
|
||||
if (error) {
|
||||
PNBUF_PUT((*path)->pathbuf);
|
||||
free(path, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
(*path)->needfree = TRUE;
|
||||
} else {
|
||||
(*path)->pathbuf = __UNCONST(dirp);
|
||||
(*path)->needfree = FALSE;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
const char *
|
||||
pathname_path(pathname_t path)
|
||||
{
|
||||
KASSERT(path != NULL);
|
||||
return (path->pathbuf);
|
||||
}
|
||||
|
||||
void
|
||||
pathname_put(pathname_t path)
|
||||
{
|
||||
if (path != NULL) {
|
||||
if (path->pathbuf != NULL && path->needfree)
|
||||
PNBUF_PUT(path->pathbuf);
|
||||
free(path, M_TEMP);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a pathname into a pointer to a locked vnode.
|
||||
*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vfs_syscalls.c,v 1.281 2006/12/14 09:24:54 yamt Exp $ */
|
||||
/* $NetBSD: vfs_syscalls.c,v 1.282 2006/12/24 08:54:55 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.281 2006/12/14 09:24:54 yamt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.282 2006/12/24 08:54:55 elad Exp $");
|
||||
|
||||
#include "opt_compat_netbsd.h"
|
||||
#include "opt_compat_43.h"
|
||||
|
@ -2015,6 +2015,9 @@ sys_unlink(struct lwp *l, void *v, register_t *retval)
|
|||
struct vnode *vp;
|
||||
int error;
|
||||
struct nameidata nd;
|
||||
#if NVERIEXEC > 0
|
||||
pathname_t pathbuf;
|
||||
#endif /* NVERIEXEC > 0 */
|
||||
|
||||
restart:
|
||||
NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
|
||||
|
@ -2038,8 +2041,15 @@ restart:
|
|||
}
|
||||
|
||||
#if NVERIEXEC > 0
|
||||
error = pathname_get(nd.ni_dirp, nd.ni_segflg, &pathbuf);
|
||||
|
||||
/* Handle remove requests for veriexec entries. */
|
||||
if ((error = veriexec_removechk(vp, nd.ni_dirp, l)) != 0) {
|
||||
if (!error) {
|
||||
error = veriexec_removechk(vp, pathname_path(pathbuf), l);
|
||||
pathname_put(pathbuf);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
|
||||
if (nd.ni_dvp == vp)
|
||||
vrele(nd.ni_dvp);
|
||||
|
@ -3364,9 +3374,21 @@ rename_files(const char *from, const char *to, struct lwp *l, int retain)
|
|||
}
|
||||
|
||||
#if NVERIEXEC > 0
|
||||
if (!error)
|
||||
error = veriexec_renamechk(fvp, fromnd.ni_dirp, tvp,
|
||||
tond.ni_dirp, l);
|
||||
if (!error) {
|
||||
pathname_t frompath, topath;
|
||||
|
||||
error = pathname_get(fromnd.ni_dirp, fromnd.ni_segflg,
|
||||
&frompath);
|
||||
if (!error)
|
||||
error = pathname_get(tond.ni_dirp, tond.ni_segflg,
|
||||
&topath);
|
||||
if (!error)
|
||||
error = veriexec_renamechk(fvp, pathname_path(frompath),
|
||||
tvp, pathname_path(topath), l);
|
||||
|
||||
pathname_put(frompath);
|
||||
pathname_put(topath);
|
||||
}
|
||||
#endif /* NVERIEXEC > 0 */
|
||||
|
||||
out:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: namei.h,v 1.46 2006/12/09 16:11:52 chs Exp $ */
|
||||
/* $NetBSD: namei.h,v 1.47 2006/12/24 08:54:55 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1985, 1989, 1991, 1993
|
||||
|
@ -182,6 +182,8 @@ extern struct pool_cache pnbuf_cache; /* pathname buffer cache */
|
|||
#define PNBUF_GET() pool_cache_get(&pnbuf_cache, PR_WAITOK)
|
||||
#define PNBUF_PUT(pnb) pool_cache_put(&pnbuf_cache, (pnb))
|
||||
|
||||
typedef struct pathname_internal *pathname_t;
|
||||
|
||||
int namei(struct nameidata *);
|
||||
uint32_t namei_hash(const char *, const char **);
|
||||
int lookup(struct nameidata *);
|
||||
|
@ -199,6 +201,10 @@ void nchinit(void);
|
|||
void nchreinit(void);
|
||||
void cache_purgevfs(struct mount *);
|
||||
void namecache_print(struct vnode *, void (*)(const char *, ...));
|
||||
|
||||
int pathname_get(const char *, enum uio_seg, pathname_t *);
|
||||
const char *pathname_path(pathname_t);
|
||||
void pathname_put(pathname_t);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue