Provide some compat32 shims for sysctl vfs.conflist. It is required

for getvfsbyname(3) operation when called from 32bit process, and
getvfsbyname(3) is used by recent bsdtar import.

Reported by:	many
Tested by:	David Naylor <naylor.b.david@gmail.com>
MFC after:	5 days
This commit is contained in:
Konstantin Belousov 2012-08-22 20:05:34 +00:00
parent 7e690c1f79
commit 258f94423b

@ -41,6 +41,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include "opt_compat.h"
#include "opt_ddb.h" #include "opt_ddb.h"
#include "opt_watchdog.h" #include "opt_watchdog.h"
@ -3111,22 +3112,50 @@ DB_SHOW_COMMAND(mount, db_show_mount)
/* /*
* Fill in a struct xvfsconf based on a struct vfsconf. * Fill in a struct xvfsconf based on a struct vfsconf.
*/ */
static void static int
vfsconf2x(struct vfsconf *vfsp, struct xvfsconf *xvfsp) vfsconf2x(struct sysctl_req *req, struct vfsconf *vfsp)
{ {
struct xvfsconf xvfsp;
strcpy(xvfsp->vfc_name, vfsp->vfc_name); bzero(&xvfsp, sizeof(xvfsp));
xvfsp->vfc_typenum = vfsp->vfc_typenum; strcpy(xvfsp.vfc_name, vfsp->vfc_name);
xvfsp->vfc_refcount = vfsp->vfc_refcount; xvfsp.vfc_typenum = vfsp->vfc_typenum;
xvfsp->vfc_flags = vfsp->vfc_flags; xvfsp.vfc_refcount = vfsp->vfc_refcount;
xvfsp.vfc_flags = vfsp->vfc_flags;
/* /*
* These are unused in userland, we keep them * These are unused in userland, we keep them
* to not break binary compatibility. * to not break binary compatibility.
*/ */
xvfsp->vfc_vfsops = NULL; xvfsp.vfc_vfsops = NULL;
xvfsp->vfc_next = NULL; xvfsp.vfc_next = NULL;
return (SYSCTL_OUT(req, &xvfsp, sizeof(xvfsp)));
} }
#ifdef COMPAT_FREEBSD32
struct xvfsconf32 {
uint32_t vfc_vfsops;
char vfc_name[MFSNAMELEN];
int32_t vfc_typenum;
int32_t vfc_refcount;
int32_t vfc_flags;
uint32_t vfc_next;
};
static int
vfsconf2x32(struct sysctl_req *req, struct vfsconf *vfsp)
{
struct xvfsconf32 xvfsp;
strcpy(xvfsp.vfc_name, vfsp->vfc_name);
xvfsp.vfc_typenum = vfsp->vfc_typenum;
xvfsp.vfc_refcount = vfsp->vfc_refcount;
xvfsp.vfc_flags = vfsp->vfc_flags;
xvfsp.vfc_vfsops = 0;
xvfsp.vfc_next = 0;
return (SYSCTL_OUT(req, &xvfsp, sizeof(xvfsp)));
}
#endif
/* /*
* Top level filesystem related information gathering. * Top level filesystem related information gathering.
*/ */
@ -3134,14 +3163,16 @@ static int
sysctl_vfs_conflist(SYSCTL_HANDLER_ARGS) sysctl_vfs_conflist(SYSCTL_HANDLER_ARGS)
{ {
struct vfsconf *vfsp; struct vfsconf *vfsp;
struct xvfsconf xvfsp;
int error; int error;
error = 0; error = 0;
TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) { TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
bzero(&xvfsp, sizeof(xvfsp)); #ifdef COMPAT_FREEBSD32
vfsconf2x(vfsp, &xvfsp); if (req->flags & SCTL_MASK32)
error = SYSCTL_OUT(req, &xvfsp, sizeof xvfsp); error = vfsconf2x32(req, vfsp);
else
#endif
error = vfsconf2x(req, vfsp);
if (error) if (error)
break; break;
} }
@ -3161,7 +3192,6 @@ vfs_sysctl(SYSCTL_HANDLER_ARGS)
int *name = (int *)arg1 - 1; /* XXX */ int *name = (int *)arg1 - 1; /* XXX */
u_int namelen = arg2 + 1; /* XXX */ u_int namelen = arg2 + 1; /* XXX */
struct vfsconf *vfsp; struct vfsconf *vfsp;
struct xvfsconf xvfsp;
log(LOG_WARNING, "userland calling deprecated sysctl, " log(LOG_WARNING, "userland calling deprecated sysctl, "
"please rebuild world\n"); "please rebuild world\n");
@ -3185,9 +3215,12 @@ vfs_sysctl(SYSCTL_HANDLER_ARGS)
break; break;
if (vfsp == NULL) if (vfsp == NULL)
return (EOPNOTSUPP); return (EOPNOTSUPP);
bzero(&xvfsp, sizeof(xvfsp)); #ifdef COMPAT_FREEBSD32
vfsconf2x(vfsp, &xvfsp); if (req->flags & SCTL_MASK32)
return (SYSCTL_OUT(req, &xvfsp, sizeof(xvfsp))); return (vfsconf2x32(req, vfsp));
else
#endif
return (vfsconf2x(req, vfsp));
} }
return (EOPNOTSUPP); return (EOPNOTSUPP);
} }