Page MenuHomeFreeBSD

D38933.id118421.diff
No OneTemporary

D38933.id118421.diff

diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -629,7 +629,7 @@
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_LINUX | SV_LP64 | SV_SHP | SV_SIG_DISCIGN |
- SV_SIG_WAITNDQ | SV_TIMEKEEP,
+ SV_SIG_WAITNDQ | SV_TIMEKEEP | SV_WANTABIPATH,
.sv_set_syscall_retval = linux_set_syscall_retval,
.sv_fetch_syscall_args = linux_fetch_syscall_args,
.sv_syscallnames = linux_syscallnames,
@@ -643,6 +643,7 @@
.sv_ontdexit = linux_thread_dtor,
.sv_setid_allowed = &linux_setid_allowed_query,
.sv_set_fork_retval = linux_set_fork_retval,
+ .sv_alterlink = linux_alternate_link,
};
static int
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -854,7 +854,7 @@
.sv_fixlimit = linux32_fixlimit,
.sv_maxssiz = &linux32_maxssiz,
.sv_flags = SV_ABI_LINUX | SV_ILP32 | SV_IA32 | SV_SHP |
- SV_SIG_DISCIGN | SV_SIG_WAITNDQ | SV_TIMEKEEP,
+ SV_SIG_DISCIGN | SV_SIG_WAITNDQ | SV_TIMEKEEP | SV_WANTABIPATH,
.sv_set_syscall_retval = linux32_set_syscall_retval,
.sv_fetch_syscall_args = linux32_fetch_syscall_args,
.sv_syscallnames = linux32_syscallnames,
@@ -868,6 +868,7 @@
.sv_ontdexit = linux_thread_dtor,
.sv_setid_allowed = &linux_setid_allowed_query,
.sv_set_fork_retval = linux32_set_fork_retval,
+ .sv_alterlink = linux_alternate_link,
};
static int
diff --git a/sys/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c
--- a/sys/arm64/linux/linux_sysvec.c
+++ b/sys/arm64/linux/linux_sysvec.c
@@ -431,7 +431,7 @@
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_LINUX | SV_LP64 | SV_SHP | SV_SIG_DISCIGN |
- SV_SIG_WAITNDQ | SV_TIMEKEEP,
+ SV_SIG_WAITNDQ | SV_TIMEKEEP | SV_WANTABIPATH,
.sv_set_syscall_retval = linux_set_syscall_retval,
.sv_fetch_syscall_args = linux_fetch_syscall_args,
.sv_syscallnames = linux_syscallnames,
@@ -446,6 +446,7 @@
.sv_onexit = linux_on_exit,
.sv_ontdexit = linux_thread_dtor,
.sv_setid_allowed = &linux_setid_allowed_query,
+ .sv_alterlink = linux_alternate_link,
};
static int
diff --git a/sys/compat/linux/linux_util.h b/sys/compat/linux/linux_util.h
--- a/sys/compat/linux/linux_util.h
+++ b/sys/compat/linux/linux_util.h
@@ -38,6 +38,8 @@
#include <sys/uio.h>
+struct nameidata;
+
MALLOC_DECLARE(M_LINUX);
MALLOC_DECLARE(M_EPOLL);
@@ -45,6 +47,7 @@
extern int linux_use_emul_path;
int linux_emul_convpath(const char *, enum uio_seg, char **, int, int);
+int linux_alternate_link(struct nameidata *, char *, int *);
#define LUSECONVPATH(td) atomic_load_int(&linux_use_emul_path)
diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c
--- a/sys/compat/linux/linux_util.c
+++ b/sys/compat/linux/linux_util.c
@@ -96,6 +96,29 @@
return (retval);
}
+int
+linux_alternate_link(struct nameidata *ndp, char *cp, int *linklen)
+{
+ size_t len;
+ char *ncp;
+
+ if (!LUSECONVPATH(td))
+ return (0);
+ if (*linklen > 0 && cp[0] == '/') {
+ len = strlen(linux_emul_path);
+ if ((*linklen + len + 2) > MAXPATHLEN)
+ return (ENAMETOOLONG);
+ cp[*linklen] = '\0';
+ len = *linklen + len;
+ ncp = malloc(len, M_TEMP, M_WAITOK);
+ sprintf(ncp, "%s%s", linux_emul_path, cp);
+ bcopy(ncp, cp, len);
+ free(ncp, M_TEMP);
+ *linklen = len;
+ }
+ return (0);
+}
+
void
linux_msg(const struct thread *td, const char *fmt, ...)
{
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -655,6 +655,7 @@
.sv_ontdexit = linux_thread_dtor,
.sv_setid_allowed = &linux_setid_allowed_query,
.sv_set_fork_retval = linux_set_fork_retval,
+ .sv_alterlink = NULL,
};
INIT_SYSENTVEC(aout_sysvec, &linux_sysvec);
@@ -684,7 +685,7 @@
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_LINUX | SV_IA32 | SV_ILP32 | SV_SHP |
- SV_SIG_DISCIGN | SV_SIG_WAITNDQ | SV_TIMEKEEP,
+ SV_SIG_DISCIGN | SV_SIG_WAITNDQ | SV_TIMEKEEP | SV_WANTABIPATH,
.sv_set_syscall_retval = linux_set_syscall_retval,
.sv_fetch_syscall_args = linux_fetch_syscall_args,
.sv_syscallnames = NULL,
@@ -698,6 +699,7 @@
.sv_ontdexit = linux_thread_dtor,
.sv_setid_allowed = &linux_setid_allowed_query,
.sv_set_fork_retval = linux_set_fork_retval,
+ .sv_alterlink = linux_alternate_link,
};
static int
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -791,6 +791,7 @@
struct nameidata *nd;
struct vattr *attr;
struct image_params *imgp;
+ uint64_t nd_flags;
u_long rbase;
u_long base_addr = 0;
int error;
@@ -815,11 +816,21 @@
imgp->proc = p;
imgp->attr = attr;
- NDINIT(nd, LOOKUP, ISOPEN | FOLLOW | LOCKSHARED | LOCKLEAF,
- UIO_SYSSPACE, file);
+ nd_flags = ISOPEN | FOLLOW | LOCKSHARED | LOCKLEAF;
+
+ NDINIT(nd, LOOKUP, nd_flags, UIO_SYSSPACE, file);
if ((error = namei(nd)) != 0) {
- nd->ni_vp = NULL;
- goto fail;
+ if (__predict_false(SV_PROC_FLAG(p, SV_WANTABIPATH) != 0)) {
+ nd_flags |= WANTABIPATH;
+ NDINIT_ABI(nd, LOOKUP, nd_flags, UIO_SYSSPACE, file, p);
+ if ((error = namei(nd)) != 0) {
+ nd->ni_vp = NULL;
+ goto fail;
+ }
+ } else {
+ nd->ni_vp = NULL;
+ goto fail;
+ }
}
NDFREE_PNBUF(nd);
imgp->vp = nd->ni_vp;
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -59,6 +59,7 @@
#include <sys/sdt.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
+#include <sys/sysent.h>
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
@@ -516,6 +517,18 @@
error = ENAMETOOLONG;
goto out;
}
+
+ /*
+ * Allow ABI to alter the link according to the ABI prefix.
+ */
+ if (__predict_false((cnp->cn_flags & WANTABIPATH) != 0)) {
+ error = (ndp->ni_sv->sv_alterlink)(ndp, cp, &linklen);
+ if (error != 0) {
+ if (ndp->ni_pathlen > 1)
+ uma_zfree(namei_zone, cp);
+ goto out;
+ }
+ }
if (ndp->ni_pathlen > 1) {
bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
uma_zfree(namei_zone, cnp->cn_pnbuf);
@@ -577,6 +590,15 @@
("%s: FAILIFEXISTS must be passed with LOCKPARENT and without LOCKLEAF",
__func__));
}
+ if ((cnp->cn_flags & WANTABIPATH) != 0) {
+ KASSERT(cnp->cn_nameiop == LOOKUP,
+ ("%s: WANTABIPATH passed for op %d", __func__, cnp->cn_nameiop));
+ KASSERT((cnp->cn_flags & FOLLOW) == FOLLOW,
+ ("%s: WANTABIPATH must be passed with FOLLOW",
+ __func__));
+ KASSERT(ndp->ni_sv != NULL,
+ ("%s: WANTABIPATH requires ni_sv", __func__));
+ }
#endif
ndp->ni_cnd.cn_cred = td->td_ucred;
KASSERT(ndp->ni_resflags == 0, ("%s: garbage in ni_resflags: %x\n",
@@ -1579,6 +1601,7 @@
{
struct nameidata nd, ndroot;
char *ptr, *buf, *cp;
+ struct proc *p;
size_t len, sz;
int error;
@@ -1629,18 +1652,19 @@
* and we want to create a file (cflag is set). We don't
* need to worry about the root comparison in this case.
*/
+ p = curproc;
if (create) {
for (cp = &ptr[len] - 1; *cp != '/'; cp--);
*cp = '\0';
- NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, buf);
+ NDINIT_ABI(&nd, LOOKUP, FOLLOW | WANTABIPATH, UIO_SYSSPACE, buf, p);
error = namei(&nd);
*cp = '/';
if (error != 0)
goto keeporig;
} else {
- NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, buf);
+ NDINIT_ABI(&nd, LOOKUP, FOLLOW | WANTABIPATH, UIO_SYSSPACE, buf, p);
error = namei(&nd);
if (error != 0)
diff --git a/sys/sys/namei.h b/sys/sys/namei.h
--- a/sys/sys/namei.h
+++ b/sys/sys/namei.h
@@ -111,6 +111,10 @@
*/
struct componentname ni_cnd;
struct nameicap_tracker_head ni_cap_tracker;
+ /*
+ * Private ABI info
+ */
+ struct sysentvec *ni_sv;
/*
* Private helper data for UFS, must be at the end. See
* NDINIT_PREFILL().
@@ -154,6 +158,7 @@
#define LOCKSHARED 0x0100 /* Shared lock leaf */
#define NOFOLLOW 0x0000 /* do not follow symbolic links (pseudo) */
#define RBENEATH 0x100000000ULL /* No escape, even tmp, from start dir */
+#define WANTABIPATH 0x200000000ULL /* Alternate ABI symlinks */
#define MODMASK 0xf000001ffULL /* mask of operational modifiers */
/*
@@ -207,13 +212,19 @@
* Initialization of a nameidata structure.
*/
#define NDINIT(ndp, op, flags, segflg, namep) \
- NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, NULL, &cap_no_rights)
+ NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, NULL, \
+ &cap_no_rights, NULL)
#define NDINIT_AT(ndp, op, flags, segflg, namep, dirfd) \
- NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, &cap_no_rights)
+ NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, \
+ &cap_no_rights, NULL)
#define NDINIT_ATRIGHTS(ndp, op, flags, segflg, namep, dirfd, rightsp) \
- NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, rightsp)
+ NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, rightsp, NULL)
#define NDINIT_ATVP(ndp, op, flags, segflg, namep, vp) \
- NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, vp, &cap_no_rights)
+ NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, vp, \
+ &cap_no_rights, NULL)
+#define NDINIT_ABI(ndp, op, flags, segflg, namep, proc) \
+ NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, NULL, \
+ &cap_no_rights, p->p_sysent)
/*
* Note the constant pattern may *hide* bugs.
@@ -238,7 +249,7 @@
#define NDREINIT_DBG(arg) do { } while (0)
#endif
-#define NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, startdir, rightsp) \
+#define NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, startdir, rightsp, sv) \
do { \
struct nameidata *_ndp = (ndp); \
cap_rights_t *_rightsp = (rightsp); \
@@ -252,6 +263,7 @@
_ndp->ni_dirfd = dirfd; \
_ndp->ni_startdir = startdir; \
_ndp->ni_resflags = 0; \
+ _ndp->ni_sv = sv; \
filecaps_init(&_ndp->ni_filecaps); \
_ndp->ni_rightsneeded = _rightsp; \
} while (0)
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -99,6 +99,7 @@
struct trapframe;
struct vnode;
struct note_info_list;
+struct nameidata;
struct sysentvec {
int sv_size; /* number of entries */
@@ -160,6 +161,7 @@
/* Only used on x86 */
struct regset **sv_regset_begin;
struct regset **sv_regset_end;
+ int (*sv_alterlink)(struct nameidata *, char *, int *);
};
#define SV_ILP32 0x000100 /* 32-bit executable. */
@@ -167,7 +169,7 @@
#define SV_IA32 0x004000 /* Intel 32-bit executable. */
#define SV_AOUT 0x008000 /* a.out executable. */
#define SV_SHP 0x010000 /* Shared page. */
-#define SV_AVAIL1 0x020000 /* Unused */
+#define SV_WANTABIPATH 0x020000 /* Requires sv_alterlink */
#define SV_TIMEKEEP 0x040000 /* Shared page timehands. */
#define SV_ASLR 0x080000 /* ASLR allowed. */
#define SV_RNG_SEED_VER 0x100000 /* random(4) reseed generation. */

File Metadata

Mime Type
text/plain
Expires
Thu, Jan 23, 9:35 PM (22 m, 25 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16064994
Default Alt Text
D38933.id118421.diff (10 KB)

Event Timeline