summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Mooney <patrick.f.mooney@gmail.com>2015-07-30 14:57:08 +0000
committerPatrick Mooney <patrick.f.mooney@gmail.com>2015-07-30 18:00:58 +0000
commit36afd076aca463269fb43107a134e0cc417e044c (patch)
tree4020817e98d5fc993748339d9d2914e71c28324a
parent6f2b4ac2461254029e30e71d710eff1b5ee7799d (diff)
downloadillumos-joyent-36afd076aca463269fb43107a134e0cc417e044c.tar.gz
OS-4571 lxbrand allow manipulation of uname release and version
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
-rw-r--r--usr/src/lib/brand/lx/lx_brand/common/lx_brand.c26
-rw-r--r--usr/src/lib/brand/lx/lx_brand/common/misc.c21
-rw-r--r--usr/src/lib/brand/lx/lx_brand/sys/lx_misc.h2
-rw-r--r--usr/src/lib/brand/lx/lx_support/lx_support.c52
-rw-r--r--usr/src/uts/common/brand/lx/io/lx_netlink.c2
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_brand.c143
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_syscall.c4
-rw-r--r--usr/src/uts/common/brand/lx/procfs/lx_prvnops.c20
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_brand.h24
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_syscalls.h1
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_types.h10
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_uname.c76
-rw-r--r--usr/src/uts/intel/Makefile.files1
13 files changed, 253 insertions, 129 deletions
diff --git a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c
index 2f9d7930b3..cdc556459e 100644
--- a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c
+++ b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c
@@ -87,7 +87,7 @@
* function should return -errno back to the Linux caller.
*/
-char lx_release[LX_VERS_MAX];
+char lx_release[LX_KERN_RELEASE_MAX];
char lx_cmd_name[MAXNAMLEN];
/*
@@ -545,7 +545,7 @@ lx_start(uintptr_t sp, uintptr_t entry)
int
lx_init(int argc, char *argv[], char *envp[])
{
- char *r;
+ char *rele, *vers;
auxv_t *ap;
long *p;
int err;
@@ -572,17 +572,23 @@ lx_init(int argc, char *argv[], char *envp[])
lx_debug_init();
- r = getenv("LX_RELEASE");
- if (r == NULL) {
- if (zone_getattr(getzoneid(), LX_KERN_VERSION_NUM, lx_release,
- sizeof (lx_release)) != sizeof (lx_release))
- (void) strlcpy(lx_release, "2.4.21", LX_VERS_MAX);
+ rele = getenv("LX_RELEASE");
+ vers = getenv("LX_VERSION");
+ if (rele == NULL) {
+ if (zone_getattr(getzoneid(), LX_ATTR_KERN_RELEASE,
+ lx_release, sizeof (lx_release)) <= 0)
+ (void) strlcpy(lx_release, "2.4.21",
+ LX_KERN_RELEASE_MAX);
} else {
- (void) strlcpy(lx_release, r, 128);
+ (void) strlcpy(lx_release, rele, LX_KERN_RELEASE_MAX);
}
+ if (syscall(SYS_brand, B_OVERRIDE_KERN_VER, rele, vers) != 0) {
+ lx_debug("failed to override kernel release/version");
+ }
lx_debug("lx_release: %s\n", lx_release);
+
/*
* Should we kill an application that attempts an unimplemented
* system call?
@@ -977,7 +983,7 @@ static lx_syscall_handler_t lx_handlers[] = {
lx_exit, /* 60: exit */
NULL, /* 61: wait4 */
NULL, /* 62: kill */
- lx_uname, /* 63: uname */
+ NULL, /* 63: uname */
lx_semget, /* 64: semget */
lx_semop, /* 65: semop */
lx_semctl, /* 66: semctl */
@@ -1367,7 +1373,7 @@ static lx_syscall_handler_t lx_handlers[] = {
lx_sigreturn, /* 119: sigreturn */
lx_clone, /* 120: clone */
lx_setdomainname, /* 121: setdomainname */
- lx_uname, /* 122: uname */
+ NULL, /* 122: uname */
NULL, /* 123: modify_ldt */
lx_adjtimex, /* 124: adjtimex */
lx_mprotect, /* 125: mprotect */
diff --git a/usr/src/lib/brand/lx/lx_brand/common/misc.c b/usr/src/lib/brand/lx/lx_brand/common/misc.c
index f56b9e8905..03a6df70dd 100644
--- a/usr/src/lib/brand/lx/lx_brand/common/misc.c
+++ b/usr/src/lib/brand/lx/lx_brand/common/misc.c
@@ -229,27 +229,6 @@ lx_getcwd(uintptr_t p1, uintptr_t p2)
return (len + 1);
}
-long
-lx_uname(uintptr_t p1)
-{
- struct lx_utsname *un = (struct lx_utsname *)p1;
- char buf[LX_SYS_UTS_LN + 1];
-
- if (gethostname(un->nodename, sizeof (un->nodename)) == -1)
- return (-errno);
-
- (void) strlcpy(un->sysname, LX_UNAME_SYSNAME, LX_SYS_UTS_LN);
- (void) strlcpy(un->release, lx_release, LX_SYS_UTS_LN);
- (void) strlcpy(un->version, LX_UNAME_VERSION, LX_SYS_UTS_LN);
- (void) strlcpy(un->machine, LX_UNAME_MACHINE, LX_SYS_UTS_LN);
- if ((sysinfo(SI_SRPC_DOMAIN, buf, LX_SYS_UTS_LN) < 0))
- un->domainname[0] = '\0';
- else
- (void) strlcpy(un->domainname, buf, LX_SYS_UTS_LN);
-
- return (0);
-}
-
/*
* {get,set}groups16() - Handle the conversion between 16-bit Linux gids and
* 32-bit illumos gids.
diff --git a/usr/src/lib/brand/lx/lx_brand/sys/lx_misc.h b/usr/src/lib/brand/lx/lx_brand/sys/lx_misc.h
index 6f1b772228..05a38a0788 100644
--- a/usr/src/lib/brand/lx/lx_brand/sys/lx_misc.h
+++ b/usr/src/lib/brand/lx/lx_brand/sys/lx_misc.h
@@ -47,7 +47,7 @@
extern "C" {
#endif
-extern char lx_release[LX_VERS_MAX];
+extern char lx_release[LX_KERN_RELEASE_MAX];
extern char lx_cmd_name[MAXNAMLEN];
extern pid_t zoneinit_pid;
diff --git a/usr/src/lib/brand/lx/lx_support/lx_support.c b/usr/src/lib/brand/lx/lx_support/lx_support.c
index d1f96defb5..f4e1a23da0 100644
--- a/usr/src/lib/brand/lx/lx_support/lx_support.c
+++ b/usr/src/lib/brand/lx/lx_support/lx_support.c
@@ -60,8 +60,6 @@ static void usage(void) __NORETURN;
#define CP_CMD "/usr/bin/cp"
#define MOUNT_CMD "/sbin/mount"
-#define KVSTRLEN 10
-
static char *bname = NULL;
static char *zonename = NULL;
static char *zoneroot = NULL;
@@ -175,7 +173,7 @@ lxs_remove_autofsck()
* Extract any lx-supported attributes from the zone configuration file.
*/
static void
-lxs_getattrs(zone_dochandle_t zdh, char **kvers)
+lxs_getattrs(zone_dochandle_t zdh, char **krelease)
{
struct zone_attrtab attrtab;
int err;
@@ -186,22 +184,22 @@ lxs_getattrs(zone_dochandle_t zdh, char **kvers)
lxs_err(gettext("error accessing zone configuration"));
}
- *kvers = (char *)malloc(KVSTRLEN);
- if (*kvers == NULL)
+ *krelease = (char *)malloc(LX_KERN_RELEASE_MAX);
+ if (*krelease == NULL)
lxs_err(gettext("out of memory"));
- bzero(*kvers, KVSTRLEN);
+ bzero(*krelease, LX_KERN_RELEASE_MAX);
while ((err = zonecfg_getattrent(zdh, &attrtab)) == Z_OK) {
if ((strcmp(attrtab.zone_attr_name, "kernel-version") == 0) &&
- (zonecfg_get_attr_string(&attrtab, *kvers,
- KVSTRLEN) != Z_OK))
+ (zonecfg_get_attr_string(&attrtab, *krelease,
+ LX_KERN_RELEASE_MAX) != Z_OK))
lxs_err(gettext("invalid type for zone attribute: %s"),
attrtab.zone_attr_name);
}
- if (strlen(*kvers) == 0) {
- free(*kvers);
- *kvers = NULL;
+ if (strlen(*krelease) == 0) {
+ free(*krelease);
+ *krelease = NULL;
}
/* some kind of error while looking up attributes */
@@ -214,7 +212,7 @@ lxs_boot()
{
zoneid_t zoneid;
zone_dochandle_t zdh;
- char *kvers;
+ char *krelease;
lxs_make_initctl();
lxs_remove_autofsck();
@@ -228,7 +226,7 @@ lxs_boot()
}
/* Extract any relevant attributes from the config file. */
- lxs_getattrs(zdh, &kvers);
+ lxs_getattrs(zdh, &krelease);
zonecfg_fini_handle(zdh);
/*
@@ -238,16 +236,16 @@ lxs_boot()
if ((zoneid = getzoneidbyname(zonename)) < 0)
lxs_err(gettext("unable to get zoneid"));
- if (kvers != NULL) {
+ if (krelease != NULL) {
/* Backward compatability with incomplete version attr */
- if (strcmp(kvers, "2.4") == 0) {
- kvers = "2.4.21";
- } else if (strcmp(kvers, "2.6") == 0) {
- kvers = "2.6.18";
+ if (strcmp(krelease, "2.4") == 0) {
+ krelease = "2.4.21";
+ } else if (strcmp(krelease, "2.6") == 0) {
+ krelease = "2.6.18";
}
- if (zone_setattr(zoneid, LX_KERN_VERSION_NUM, kvers,
- strlen(kvers)) < 0)
+ if (zone_setattr(zoneid, LX_ATTR_KERN_RELEASE, krelease,
+ strlen(krelease)) < 0)
lxs_err(gettext("unable to set kernel version"));
}
@@ -264,7 +262,7 @@ static int
lxs_verify(char *xmlfile)
{
zone_dochandle_t handle;
- char *kvers;
+ char *krelease;
char hostidp[HW_HOSTID_LEN];
zone_iptype_t iptype;
@@ -294,14 +292,14 @@ lxs_verify(char *xmlfile)
}
/* Extract any relevant attributes from the config file. */
- lxs_getattrs(handle, &kvers);
+ lxs_getattrs(handle, &krelease);
zonecfg_fini_handle(handle);
- if (kvers) {
- if (strlen(kvers) > (LX_VERS_MAX - 1) ||
- (strncmp(kvers, "2.4", 3) != 0 &&
- strncmp(kvers, "2.6", 3) != 0 &&
- strncmp(kvers, "3.", 2) != 0))
+ if (krelease) {
+ if (strlen(krelease) >= LX_KERN_RELEASE_MAX ||
+ (strncmp(krelease, "2.4", 3) != 0 &&
+ strncmp(krelease, "2.6", 3) != 0 &&
+ strncmp(krelease, "3.", 2) != 0))
lxs_err(gettext("invalid value for zone attribute: %s"),
"kernel-version");
}
diff --git a/usr/src/uts/common/brand/lx/io/lx_netlink.c b/usr/src/uts/common/brand/lx/io/lx_netlink.c
index 2e80e1bf11..36b0cf9b2b 100644
--- a/usr/src/uts/common/brand/lx/io/lx_netlink.c
+++ b/usr/src/uts/common/brand/lx/io/lx_netlink.c
@@ -1239,7 +1239,7 @@ lx_netlink_getroute(lx_netlink_sock_t *lxsock, lx_netlink_hdr_t *hdr,
* truncate our input to prevent later confusion.
*/
if (curproc->p_zone->zone_brand == &lx_brand &&
- lx_kern_version_cmp(curproc->p_zone, "2.6.32") <= 0 &&
+ lx_kern_release_cmp(curproc->p_zone, "2.6.32") <= 0 &&
rtmsgp->rtm_dst_len == 0) {
rtmsg_size = sizeof (rtmsg.rtm_family);
}
diff --git a/usr/src/uts/common/brand/lx/os/lx_brand.c b/usr/src/uts/common/brand/lx/os/lx_brand.c
index 44acdff3b1..5dc026a21e 100644
--- a/usr/src/uts/common/brand/lx/os/lx_brand.c
+++ b/usr/src/uts/common/brand/lx/os/lx_brand.c
@@ -364,36 +364,77 @@ lx_setbrand(proc_t *p)
/* ARGSUSED */
int
-lx_setattr(zone_t *zone, int attr, void *buf, size_t bufsize)
+lx_setattr(zone_t *zone, int attr, void *ubuf, size_t ubufsz)
{
- char vers[LX_VERS_MAX];
+ lx_zone_data_t *lxzd = (lx_zone_data_t *)zone->zone_brand_data;
- if (attr == LX_KERN_VERSION_NUM) {
- if (bufsize > (LX_VERS_MAX - 1))
+ switch (attr) {
+ case LX_ATTR_KERN_RELEASE: {
+ char buf[LX_KERN_RELEASE_MAX];
+ bzero(buf, LX_KERN_RELEASE_MAX);
+ if (ubufsz >= LX_KERN_RELEASE_MAX) {
return (ERANGE);
- bzero(vers, LX_VERS_MAX);
- if (copyin(buf, &vers, bufsize) != 0)
+ }
+ if (copyin(ubuf, buf, ubufsz) != 0) {
return (EFAULT);
- lx_set_kern_version(zone, vers);
+ }
+ (void) strlcpy(lxzd->lxzd_kernel_release, buf,
+ LX_KERN_RELEASE_MAX);
return (0);
}
- return (EINVAL);
+ case LX_ATTR_KERN_VERSION: {
+ char buf[LX_KERN_VERSION_MAX];
+ bzero(buf, LX_KERN_VERSION_MAX);
+ if (ubufsz >= LX_KERN_VERSION_MAX) {
+ return (ERANGE);
+ }
+ if (copyin(ubuf, buf, ubufsz) != 0) {
+ return (EFAULT);
+ }
+ (void) strlcpy(lxzd->lxzd_kernel_version, buf,
+ LX_KERN_VERSION_MAX);
+ return (0);
+ }
+ default:
+ return (EINVAL);
+ }
}
/* ARGSUSED */
int
-lx_getattr(zone_t *zone, int attr, void *buf, size_t *bufsize)
+lx_getattr(zone_t *zone, int attr, void *ubuf, size_t *ubufsz)
{
- if (attr == LX_KERN_VERSION_NUM) {
- if (*bufsize < LX_VERS_MAX)
+ lx_zone_data_t *lxzd = (lx_zone_data_t *)zone->zone_brand_data;
+ int len;
+
+ switch (attr) {
+ case LX_ATTR_KERN_RELEASE: {
+ len = strnlen(lxzd->lxzd_kernel_release, LX_KERN_RELEASE_MAX);
+ len++;
+ if (*ubufsz < len) {
return (ERANGE);
- if (copyout(lx_get_zone_kern_version(curzone), buf,
- LX_VERS_MAX) != 0)
+ }
+ if (copyout(lxzd->lxzd_kernel_release, ubuf, len) != 0) {
return (EFAULT);
- *bufsize = LX_VERS_MAX;
+ }
+ *ubufsz = len;
return (0);
}
- return (-EINVAL);
+ case LX_ATTR_KERN_VERSION: {
+ len = strnlen(lxzd->lxzd_kernel_version, LX_KERN_VERSION_MAX);
+ len++;
+ if (*ubufsz < len) {
+ return (ERANGE);
+ }
+ if (copyout(lxzd->lxzd_kernel_version, ubuf, len) != 0) {
+ return (EFAULT);
+ }
+ *ubufsz = len;
+ return (0);
+ }
+ default:
+ return (EINVAL);
+ }
}
uint32_t
@@ -725,7 +766,10 @@ lx_init_brand_data(zone_t *zone)
* Set the default lxzd_kernel_version to 2.4.
* This can be changed by a call to setattr() during zone boot.
*/
- (void) strlcpy(data->lxzd_kernel_version, "2.4.21", LX_VERS_MAX);
+ (void) strlcpy(data->lxzd_kernel_release, "2.4.21",
+ LX_KERN_RELEASE_MAX);
+ (void) strlcpy(data->lxzd_kernel_version, "BrandZ virtual linux",
+ LX_KERN_VERSION_MAX);
/*
* Linux is not at all picky about address family when it comes to
@@ -1369,32 +1413,43 @@ lx_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2,
exit(code, sig);
/* NOTREACHED */
break;
- }
- return (EINVAL);
-}
+ case B_OVERRIDE_KERN_VER: {
+ void *urel = (void *)arg1;
+ void *uver = (void *)arg2;
+ size_t len;
-char *
-lx_get_zone_kern_version(zone_t *zone)
-{
- return (((lx_zone_data_t *)zone->zone_brand_data)->lxzd_kernel_version);
-}
+ pd = ptolxproc(p);
+ if (urel != NULL) {
+ if (copyinstr(urel, pd->l_uname_release,
+ LX_KERN_RELEASE_MAX, &len) != 0) {
+ return (EFAULT);
+ }
+ pd->l_uname_release[LX_KERN_RELEASE_MAX - 1] = '\0';
+ }
+ if (uver != NULL) {
+ if (copyinstr(uver, pd->l_uname_version,
+ LX_KERN_VERSION_MAX, &len) != 0) {
+ return (EFAULT);
+ }
+ pd->l_uname_version[LX_KERN_VERSION_MAX - 1] = '\0';
+ }
-void
-lx_set_kern_version(zone_t *zone, char *vers)
-{
- lx_zone_data_t *lxzd = (lx_zone_data_t *)zone->zone_brand_data;
+ return (0);
+ }
- (void) strlcpy(lxzd->lxzd_kernel_version, vers, LX_VERS_MAX);
+ }
+
+ return (EINVAL);
}
/*
* Compare linux kernel version to the one set for the zone.
* Returns greater than 0 if zone version is higher, less than 0 if the zone
- * version is lower, and 0 if the version are equal.
+ * version is lower, and 0 if the versions are equal.
*/
int
-lx_kern_version_cmp(zone_t *zone, const char *vers)
+lx_kern_release_cmp(zone_t *zone, const char *vers)
{
int zvers[3] = {0, 0, 0};
int cvers[3] = {0, 0, 0};
@@ -1402,7 +1457,7 @@ lx_kern_version_cmp(zone_t *zone, const char *vers)
VERIFY(zone->zone_brand == &lx_brand);
- (void) sscanf(ztolxzd(zone)->lxzd_kernel_version, "%d.%d.%d", &zvers[0],
+ (void) sscanf(ztolxzd(zone)->lxzd_kernel_release, "%d.%d.%d", &zvers[0],
&zvers[1], &zvers[2]);
(void) sscanf(vers, "%d.%d.%d", &cvers[0], &cvers[1], &cvers[2]);
@@ -1444,17 +1499,25 @@ lx_setid_clear(vattr_t *vap, cred_t *cr)
* Copy the per-process brand data from a parent proc to a child.
*/
void
-lx_copy_procdata(proc_t *child, proc_t *parent)
+lx_copy_procdata(proc_t *cp, proc_t *pp)
{
- lx_proc_data_t *cpd = child->p_brand_data;
- lx_proc_data_t *ppd = parent->p_brand_data;
+ lx_proc_data_t *cpd, *ppd;
+ char buf_version[LX_SYS_UTS_LN];
+
+ /*
+ * Since b_copy_procdata is called during getproc(), while the child
+ * process is still being initialized, acquiring cp->p_lock should not
+ * be required.
+ */
+ VERIFY(cp->p_brand == &lx_brand);
+ VERIFY(cpd = cp->p_brand_data);
- VERIFY(parent->p_brand == &lx_brand);
- VERIFY(child->p_brand == &lx_brand);
- VERIFY(ppd != NULL);
- VERIFY(cpd != NULL);
+ mutex_enter(&pp->p_lock);
+ VERIFY(pp->p_brand == &lx_brand);
+ VERIFY(ppd = pp->p_brand_data);
- *cpd = *ppd;
+ bcopy(ppd, cpd, sizeof (lx_proc_data_t));
+ mutex_exit(&pp->p_lock);
cpd->l_fake_limits[LX_RLFAKE_LOCKS].rlim_cur = LX_RLIM64_INFINITY;
cpd->l_fake_limits[LX_RLFAKE_LOCKS].rlim_max = LX_RLIM64_INFINITY;
diff --git a/usr/src/uts/common/brand/lx/os/lx_syscall.c b/usr/src/uts/common/brand/lx/os/lx_syscall.c
index 0598a7d997..ad52900dba 100644
--- a/usr/src/uts/common/brand/lx/os/lx_syscall.c
+++ b/usr/src/uts/common/brand/lx/os/lx_syscall.c
@@ -645,7 +645,7 @@ lx_sysent_t lx_sysent32[] = {
{"sigreturn", NULL, 0, 1}, /* 119 */
{"clone", NULL, 0, 5}, /* 120 */
{"setdomainname", NULL, 0, 2}, /* 121 */
- {"uname", NULL, 0, 1}, /* 122 */
+ {"uname", lx_uname, 0, 1}, /* 122 */
{"modify_ldt", lx_modify_ldt, 0, 3}, /* 123 */
{"adjtimex", NULL, 0, 1}, /* 124 */
{"mprotect", NULL, 0, 3}, /* 125 */
@@ -957,7 +957,7 @@ lx_sysent_t lx_sysent64[] = {
{"exit", NULL, 0, 1}, /* 60 */
{"wait4", lx_wait4, 0, 4}, /* 61 */
{"kill", lx_kill, 0, 2}, /* 62 */
- {"uname", NULL, 0, 1}, /* 63 */
+ {"uname", lx_uname, 0, 1}, /* 63 */
{"semget", NULL, 0, 3}, /* 64 */
{"semop", NULL, 0, 3}, /* 65 */
{"semctl", NULL, 0, 4}, /* 66 */
diff --git a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c
index 1cc74357ce..cde72b42bb 100644
--- a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c
+++ b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c
@@ -3408,14 +3408,12 @@ lxpr_read_diskstats(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
static void
lxpr_read_version(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
{
- char *vers;
-
- vers = lx_get_zone_kern_version(LXPTOZ(lxpnp));
+ lx_zone_data_t *lxzd = ztolxzd(LXPTOZ(lxpnp));
lxpr_uiobuf_printf(uiobuf,
"%s version %s (%s version %d.%d.%d) "
"#%s SMP %s\n",
- LX_UNAME_SYSNAME, vers,
+ LX_UNAME_SYSNAME, lxzd->lxzd_kernel_release,
#if defined(__GNUC__)
"gcc",
__GNUC__,
@@ -3427,7 +3425,7 @@ lxpr_read_version(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
(__SUNPRO_C & 0xff) / 0x10,
__SUNPRO_C & 0xf,
#endif
- LX_UNAME_VERSION,
+ lxzd->lxzd_kernel_version,
"00:00:00 00/00/00");
}
@@ -3456,7 +3454,8 @@ lxpr_read_stat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
ulong_t pswitch_cum = 0;
ulong_t forks_cum = 0;
hrtime_t msnsecs[NCMSTATES];
- char *lx_kern_version = lx_get_zone_kern_version(LXPTOZ(lxpnp));
+ /* is the emulated release > 2.4 */
+ boolean_t newer_than24 = lx_kern_release_cmp(LXPTOZ(lxpnp), "2.4") > 0;
/* temporary variable since scalehrtime modifies data in place */
hrtime_t tmptime;
@@ -3489,7 +3488,8 @@ lxpr_read_stat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
pgswapin_cum += CPU_STATS(cp, vm.pgswapin);
pgswapout_cum += CPU_STATS(cp, vm.pgswapout);
- if (strncmp(lx_kern_version, "2.4", 3) != 0) {
+
+ if (newer_than24) {
cpu_nrunnable_cum += cp->cpu_disp->disp_nrunnable;
w_io_cum += CPU_STATS(cp, sys.iowait);
for (i = 0; i < NCMSTATES; i++) {
@@ -3512,7 +3512,7 @@ lxpr_read_stat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
cp = cp->cpu_next;
} while (cp != cpstart);
- if (strncmp(lx_kern_version, "2.4", 3) != 0) {
+ if (newer_than24) {
lxpr_uiobuf_printf(uiobuf,
"cpu %lu %lu %lu %lu %lu %lu %lu\n",
user_cum, 0L, sys_cum, idle_cum, 0L, irq_cum, 0L);
@@ -3551,7 +3551,7 @@ lxpr_read_stat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
irq_ticks += NSEC_TO_TICK(tmptime);
}
- if (strncmp(lx_kern_version, "2.4", 3) != 0) {
+ if (newer_than24) {
lxpr_uiobuf_printf(uiobuf,
"cpu%d %lu %lu %lu %lu %lu %lu %lu\n",
cp->cpu_id, user_ticks, 0L, sys_ticks, idle_ticks,
@@ -3571,7 +3571,7 @@ lxpr_read_stat(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf)
mutex_exit(&cpu_lock);
- if (strncmp(lx_kern_version, "2.4", 3) != 0) {
+ if (newer_than24) {
lxpr_uiobuf_printf(uiobuf,
"page %lu %lu\n"
"swap %lu %lu\n"
diff --git a/usr/src/uts/common/brand/lx/sys/lx_brand.h b/usr/src/uts/common/brand/lx/sys/lx_brand.h
index 895ea44db5..7198bea59c 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_brand.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_brand.h
@@ -97,6 +97,7 @@ extern "C" {
#define B_HELPER_TGSIGQUEUE 146
#define B_SET_NATIVE_STACK 147
#define B_SIGEV_THREAD_ID 148
+#define B_OVERRIDE_KERN_VER 149
#ifndef _ASM
/*
@@ -143,7 +144,8 @@ typedef enum lx_ptrace_options {
#define LX_VERSION_1 1
#define LX_VERSION LX_VERSION_1
-#define LX_KERN_VERSION_NUM ZONE_ATTR_BRAND_ATTRS
+#define LX_ATTR_KERN_RELEASE ZONE_ATTR_BRAND_ATTRS
+#define LX_ATTR_KERN_VERSION (ZONE_ATTR_BRAND_ATTRS + 1)
/*
* Aux vector containing phdr of Linux executable and ehdr of interpreter
@@ -382,6 +384,13 @@ typedef enum lx_proc_flags {
#define LX_PROC_ALL (LX_PROC_INSTALL_MODE | LX_PROC_STRICT_MODE)
+/* Maximum length for fields of LX uname */
+#define LX_SYS_UTS_LN 65
+
+/* Max. length of kernel release string */
+#define LX_KERN_RELEASE_MAX LX_SYS_UTS_LN
+#define LX_KERN_VERSION_MAX LX_SYS_UTS_LN
+
#ifdef _KERNEL
/*
@@ -418,6 +427,10 @@ typedef struct lx_proc_data {
lx_proc_flags_t l_flags;
lx_rlimit64_t l_fake_limits[LX_RLFAKE_NLIMITS];
+
+ /* Override zone-wide settings for uname release and version */
+ char l_uname_release[LX_KERN_RELEASE_MAX];
+ char l_uname_version[LX_KERN_VERSION_MAX];
} lx_proc_data_t;
#endif /* _KERNEL */
@@ -431,9 +444,6 @@ typedef struct lx_proc_data {
#define LX_AFF_ULONGS (LX_NCPU / (8 * sizeof (ulong_t)))
typedef ulong_t lx_affmask_t[LX_AFF_ULONGS];
-/* Max. length of kernel version string */
-#define LX_VERS_MAX 16
-
/* Length of proc boot_id string */
#define LX_BOOTID_LEN 37
@@ -649,7 +659,8 @@ struct lx_lwp_data {
* enhanced to support different mounts with different subsystem controllers.
*/
typedef struct lx_zone_data {
- char lxzd_kernel_version[LX_VERS_MAX];
+ char lxzd_kernel_release[LX_KERN_RELEASE_MAX];
+ char lxzd_kernel_version[LX_KERN_VERSION_MAX];
ksocket_t lxzd_ioctl_sock;
char lxzd_bootid[LX_BOOTID_LEN]; /* procfs boot_id */
vfs_t *lxzd_cgroup; /* cgroup for this zone */
@@ -684,8 +695,7 @@ typedef struct lx_zone_data {
#define LX_MAX_SYSCALL(lwp) lx_nsysent32
#endif
-extern char *lx_get_zone_kern_version(zone_t *);
-extern int lx_kern_version_cmp(zone_t *, const char *);
+extern int lx_kern_release_cmp(zone_t *, const char *);
extern void lx_lwp_set_native_stack_current(lx_lwp_data_t *, uintptr_t);
extern void lx_divert(klwp_t *, uintptr_t);
diff --git a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
index c4a2307592..3202bb5455 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
@@ -108,6 +108,7 @@ extern long lx_sysinfo64();
extern long lx_tgkill();
extern long lx_time();
extern long lx_tkill();
+extern long lx_uname();
extern long lx_wait4();
extern long lx_waitid();
extern long lx_waitpid();
diff --git a/usr/src/uts/common/brand/lx/sys/lx_types.h b/usr/src/uts/common/brand/lx/sys/lx_types.h
index e91484c16b..9293d00ae1 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_types.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_types.h
@@ -54,16 +54,6 @@ extern "C" {
#endif /* !_KERNEL */
-#define LX_SYS_UTS_LN 65
-
-struct lx_utsname {
- char sysname[LX_SYS_UTS_LN];
- char nodename[LX_SYS_UTS_LN];
- char release[LX_SYS_UTS_LN];
- char version[LX_SYS_UTS_LN];
- char machine[LX_SYS_UTS_LN];
- char domainname[LX_SYS_UTS_LN];
-};
typedef uint64_t lx_dev_t;
typedef uint16_t lx_dev16_t;
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_uname.c b/usr/src/uts/common/brand/lx/syscall/lx_uname.c
new file mode 100644
index 0000000000..1b9f6b31c1
--- /dev/null
+++ b/usr/src/uts/common/brand/lx/syscall/lx_uname.c
@@ -0,0 +1,76 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Joyent, Inc.
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/thread.h>
+#include <sys/proc.h>
+#include <sys/zone.h>
+#include <sys/brand.h>
+#include <sys/lx_brand.h>
+#include <sys/lx_types.h>
+
+struct lx_utsname {
+ char lxu_sysname[LX_SYS_UTS_LN];
+ char lxu_nodename[LX_SYS_UTS_LN];
+ char lxu_release[LX_SYS_UTS_LN];
+ char lxu_version[LX_SYS_UTS_LN];
+ char lxu_machine[LX_SYS_UTS_LN];
+ char lxu_domainname[LX_SYS_UTS_LN];
+};
+
+long
+lx_uname(void *uptr)
+{
+ proc_t *p = curproc;
+ lx_proc_data_t *lxpd = ptolxproc(p);
+ lx_zone_data_t *lxzd = ztolxzd(p->p_zone);
+ struct lx_utsname un;
+
+ bzero(&un, sizeof (un));
+
+ (void) strlcpy(un.lxu_sysname, LX_UNAME_SYSNAME, LX_SYS_UTS_LN);
+ (void) strlcpy(un.lxu_nodename, p->p_zone->zone_nodename,
+ LX_SYS_UTS_LN);
+ if (lxpd->l_uname_release[0] != '\0') {
+ (void) strlcpy(un.lxu_release, lxpd->l_uname_release,
+ LX_SYS_UTS_LN);
+ } else {
+ (void) strlcpy(un.lxu_release, lxzd->lxzd_kernel_release,
+ LX_SYS_UTS_LN);
+ }
+ if (lxpd->l_uname_version[0] != '\0') {
+ (void) strlcpy(un.lxu_version, lxpd->l_uname_version,
+ LX_SYS_UTS_LN);
+ } else {
+ (void) strlcpy(un.lxu_version, lxzd->lxzd_kernel_version,
+ LX_SYS_UTS_LN);
+ }
+ if (get_udatamodel() == DATAMODEL_LP64) {
+ (void) strlcpy(un.lxu_machine, LX_UNAME_MACHINE64,
+ LX_SYS_UTS_LN);
+ } else {
+ (void) strlcpy(un.lxu_machine, LX_UNAME_MACHINE32,
+ LX_SYS_UTS_LN);
+ }
+ (void) strlcpy(un.lxu_domainname, p->p_zone->zone_domain,
+ LX_SYS_UTS_LN);
+
+ if (copyout(&un, uptr, sizeof (un)) != 0) {
+ return (set_errno(EFAULT));
+ }
+
+ return (0);
+}
diff --git a/usr/src/uts/intel/Makefile.files b/usr/src/uts/intel/Makefile.files
index 236e824127..78c9de19f2 100644
--- a/usr/src/uts/intel/Makefile.files
+++ b/usr/src/uts/intel/Makefile.files
@@ -321,6 +321,7 @@ LX_BRAND_OBJS = \
lx_sysinfo.o \
lx_thread_area.o \
lx_timer.o \
+ lx_uname.o \
lx_wait.o \
lx_xattr.o