150465Smarcel/*- 250465Smarcel * Copyright (c) 1999 Marcel Moolenaar 350465Smarcel * All rights reserved. 450465Smarcel * 550465Smarcel * Redistribution and use in source and binary forms, with or without 650465Smarcel * modification, are permitted provided that the following conditions 750465Smarcel * are met: 850465Smarcel * 1. Redistributions of source code must retain the above copyright 950465Smarcel * notice, this list of conditions and the following disclaimer 1050465Smarcel * in this position and unchanged. 1150465Smarcel * 2. Redistributions in binary form must reproduce the above copyright 1250465Smarcel * notice, this list of conditions and the following disclaimer in the 1350465Smarcel * documentation and/or other materials provided with the distribution. 1450465Smarcel * 3. The name of the author may not be used to endorse or promote products 1565067Smarcel * derived from this software without specific prior written permission. 1650465Smarcel * 1750465Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1850465Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1950465Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2050465Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2150465Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2250465Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2350465Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2450465Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2550465Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2650465Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2750465Smarcel */ 2850465Smarcel 29116173Sobrien#include <sys/cdefs.h> 30116173Sobrien__FBSDID("$FreeBSD$"); 31116173Sobrien 3250465Smarcel#include <sys/param.h> 3350465Smarcel#include <sys/kernel.h> 34235063Snetchild#include <sys/sdt.h> 3550465Smarcel#include <sys/systm.h> 3650465Smarcel#include <sys/sysctl.h> 3750465Smarcel#include <sys/proc.h> 3850465Smarcel#include <sys/malloc.h> 39191896Sjamie#include <sys/mount.h> 4050465Smarcel#include <sys/jail.h> 4187275Srwatson#include <sys/lock.h> 42191896Sjamie#include <sys/sx.h> 4350465Smarcel 4464907Smarcel#include <compat/linux/linux_mib.h> 45246085Sjhb#include <compat/linux/linux_misc.h> 4650465Smarcel 4750465Smarcelstruct linux_prison { 4850465Smarcel char pr_osname[LINUX_MAX_UTSNAME]; 4950465Smarcel char pr_osrelease[LINUX_MAX_UTSNAME]; 5050465Smarcel int pr_oss_version; 51191972Sdchagin int pr_osrel; 5250465Smarcel}; 5350465Smarcel 54192895Sjamiestatic struct linux_prison lprison0 = { 55192895Sjamie .pr_osname = "Linux", 56293496Sdchagin .pr_osrelease = LINUX_VERSION_STR, 57192895Sjamie .pr_oss_version = 0x030600, 58293496Sdchagin .pr_osrel = LINUX_VERSION_CODE 59192895Sjamie}; 60192895Sjamie 61191896Sjamiestatic unsigned linux_osd_jail_slot; 62191896Sjamie 63293527SdchaginSYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0, "Linux mode"); 6450465Smarcel 65219668Snetchildstatic int linux_set_osname(struct thread *td, char *osname); 66219668Snetchildstatic int linux_set_osrelease(struct thread *td, char *osrelease); 67219668Snetchildstatic int linux_set_oss_version(struct thread *td, int oss_version); 68219668Snetchild 6950465Smarcelstatic int 7062573Sphklinux_sysctl_osname(SYSCTL_HANDLER_ARGS) 7150465Smarcel{ 7250465Smarcel char osname[LINUX_MAX_UTSNAME]; 7350465Smarcel int error; 7450465Smarcel 75112206Sjhb linux_get_osname(req->td, osname); 7650465Smarcel error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req); 77293527Sdchagin if (error != 0 || req->newptr == NULL) 7850465Smarcel return (error); 79112206Sjhb error = linux_set_osname(req->td, osname); 80235063Snetchild 8150465Smarcel return (error); 8250465Smarcel} 8350465Smarcel 8450465SmarcelSYSCTL_PROC(_compat_linux, OID_AUTO, osname, 85191792Sjamie CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 8650465Smarcel 0, 0, linux_sysctl_osname, "A", 8750465Smarcel "Linux kernel OS name"); 8850465Smarcel 8950465Smarcelstatic int 9062573Sphklinux_sysctl_osrelease(SYSCTL_HANDLER_ARGS) 9150465Smarcel{ 9250465Smarcel char osrelease[LINUX_MAX_UTSNAME]; 9350465Smarcel int error; 9450465Smarcel 95112206Sjhb linux_get_osrelease(req->td, osrelease); 9650465Smarcel error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req); 97293527Sdchagin if (error != 0 || req->newptr == NULL) 9850465Smarcel return (error); 99112206Sjhb error = linux_set_osrelease(req->td, osrelease); 100235063Snetchild 10150465Smarcel return (error); 10250465Smarcel} 10350465Smarcel 10450465SmarcelSYSCTL_PROC(_compat_linux, OID_AUTO, osrelease, 105191792Sjamie CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 10650465Smarcel 0, 0, linux_sysctl_osrelease, "A", 10750465Smarcel "Linux kernel OS release"); 10850465Smarcel 10950465Smarcelstatic int 11062573Sphklinux_sysctl_oss_version(SYSCTL_HANDLER_ARGS) 11150465Smarcel{ 11250465Smarcel int oss_version; 11350465Smarcel int error; 11450465Smarcel 115112206Sjhb oss_version = linux_get_oss_version(req->td); 11650465Smarcel error = sysctl_handle_int(oidp, &oss_version, 0, req); 117293527Sdchagin if (error != 0 || req->newptr == NULL) 11850465Smarcel return (error); 119112206Sjhb error = linux_set_oss_version(req->td, oss_version); 120235063Snetchild 12150465Smarcel return (error); 12250465Smarcel} 12350465Smarcel 12450465SmarcelSYSCTL_PROC(_compat_linux, OID_AUTO, oss_version, 125191792Sjamie CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 12650465Smarcel 0, 0, linux_sysctl_oss_version, "I", 12750465Smarcel "Linux OSS version"); 12850465Smarcel 12987275Srwatson/* 130191972Sdchagin * Map the osrelease into integer 131191972Sdchagin */ 132191972Sdchaginstatic int 133191972Sdchaginlinux_map_osrel(char *osrelease, int *osrel) 134191972Sdchagin{ 135191972Sdchagin char *sep, *eosrelease; 136191972Sdchagin int len, v0, v1, v2, v; 137191972Sdchagin 138191972Sdchagin len = strlen(osrelease); 139191972Sdchagin eosrelease = osrelease + len; 140191972Sdchagin v0 = strtol(osrelease, &sep, 10); 141293527Sdchagin if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.') 142191972Sdchagin return (EINVAL); 143191972Sdchagin osrelease = sep + 1; 144191972Sdchagin v1 = strtol(osrelease, &sep, 10); 145293527Sdchagin if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.') 146191972Sdchagin return (EINVAL); 147191972Sdchagin osrelease = sep + 1; 148191972Sdchagin v2 = strtol(osrelease, &sep, 10); 149293527Sdchagin if (osrelease == sep || sep != eosrelease) 150191972Sdchagin return (EINVAL); 151191972Sdchagin 152191972Sdchagin v = v0 * 1000000 + v1 * 1000 + v2; 153293527Sdchagin if (v < 1000000) 154191972Sdchagin return (EINVAL); 155191972Sdchagin 156191972Sdchagin *osrel = v; 157235063Snetchild 158191972Sdchagin return (0); 159191972Sdchagin} 160191972Sdchagin 161191972Sdchagin/* 162192895Sjamie * Find a prison with Linux info. 163192895Sjamie * Return the Linux info and the (locked) prison. 16487275Srwatson */ 165191896Sjamiestatic struct linux_prison * 166192895Sjamielinux_find_prison(struct prison *spr, struct prison **prp) 16750465Smarcel{ 168191896Sjamie struct prison *pr; 169191896Sjamie struct linux_prison *lpr; 17050465Smarcel 171192895Sjamie if (!linux_osd_jail_slot) 172192895Sjamie /* In case osd_register failed. */ 173192895Sjamie spr = &prison0; 174192895Sjamie for (pr = spr;; pr = pr->pr_parent) { 175192895Sjamie mtx_lock(&pr->pr_mtx); 176192895Sjamie lpr = (pr == &prison0) 177192895Sjamie ? &lprison0 178192895Sjamie : osd_jail_get(pr, linux_osd_jail_slot); 179192895Sjamie if (lpr != NULL) 180192895Sjamie break; 181191896Sjamie mtx_unlock(&pr->pr_mtx); 182192895Sjamie } 183192895Sjamie *prp = pr; 184235063Snetchild 185191896Sjamie return (lpr); 186191896Sjamie} 187191896Sjamie 188191896Sjamie/* 189192895Sjamie * Ensure a prison has its own Linux info. If lprp is non-null, point it to 190192895Sjamie * the Linux info and lock the prison. 191191896Sjamie */ 192191896Sjamiestatic int 193191896Sjamielinux_alloc_prison(struct prison *pr, struct linux_prison **lprp) 194191896Sjamie{ 195192895Sjamie struct prison *ppr; 196191896Sjamie struct linux_prison *lpr, *nlpr; 197191896Sjamie int error; 198191896Sjamie 199191896Sjamie /* If this prison already has Linux info, return that. */ 200191896Sjamie error = 0; 201192895Sjamie lpr = linux_find_prison(pr, &ppr); 202192895Sjamie if (ppr == pr) 203191896Sjamie goto done; 204191896Sjamie /* 205191896Sjamie * Allocate a new info record. Then check again, in case something 206191896Sjamie * changed during the allocation. 207191896Sjamie */ 208192895Sjamie mtx_unlock(&ppr->pr_mtx); 209191896Sjamie nlpr = malloc(sizeof(struct linux_prison), M_PRISON, M_WAITOK); 210192895Sjamie lpr = linux_find_prison(pr, &ppr); 211192895Sjamie if (ppr == pr) { 212191896Sjamie free(nlpr, M_PRISON); 213191896Sjamie goto done; 214191896Sjamie } 215192895Sjamie /* Inherit the initial values from the ancestor. */ 216192895Sjamie mtx_lock(&pr->pr_mtx); 217191896Sjamie error = osd_jail_set(pr, linux_osd_jail_slot, nlpr); 218192895Sjamie if (error == 0) { 219192895Sjamie bcopy(lpr, nlpr, sizeof(*lpr)); 220192895Sjamie lpr = nlpr; 221192895Sjamie } else { 222191896Sjamie free(nlpr, M_PRISON); 223192895Sjamie lpr = NULL; 224191896Sjamie } 225192895Sjamie mtx_unlock(&ppr->pr_mtx); 226192895Sjamie done: 227191896Sjamie if (lprp != NULL) 228191896Sjamie *lprp = lpr; 229192895Sjamie else 230192895Sjamie mtx_unlock(&pr->pr_mtx); 231235063Snetchild 232191896Sjamie return (error); 233191896Sjamie} 234191896Sjamie 235191896Sjamie/* 236191896Sjamie * Jail OSD methods for Linux prison data. 237191896Sjamie */ 238191896Sjamiestatic int 239191896Sjamielinux_prison_create(void *obj, void *data) 240191896Sjamie{ 241191896Sjamie struct prison *pr = obj; 242191896Sjamie struct vfsoptlist *opts = data; 243293527Sdchagin int jsys; 244191896Sjamie 245293527Sdchagin if (vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)) == 0 && 246293527Sdchagin jsys == JAIL_SYS_INHERIT) 247191896Sjamie return (0); 248191896Sjamie /* 249191896Sjamie * Inherit a prison's initial values from its parent 250195870Sjamie * (different from JAIL_SYS_INHERIT which also inherits changes). 251191896Sjamie */ 252293527Sdchagin return (linux_alloc_prison(pr, NULL)); 253191896Sjamie} 254191896Sjamie 255191896Sjamiestatic int 256191896Sjamielinux_prison_check(void *obj __unused, void *data) 257191896Sjamie{ 258191896Sjamie struct vfsoptlist *opts = data; 259191896Sjamie char *osname, *osrelease; 260195870Sjamie int error, jsys, len, osrel, oss_version; 261191896Sjamie 262191896Sjamie /* Check that the parameters are correct. */ 263195870Sjamie error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)); 264195870Sjamie if (error != ENOENT) { 265293527Sdchagin if (error != 0) 266195870Sjamie return (error); 267293527Sdchagin if (jsys != JAIL_SYS_NEW && jsys != JAIL_SYS_INHERIT) 268195870Sjamie return (EINVAL); 269195870Sjamie } 270191896Sjamie error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len); 271191896Sjamie if (error != ENOENT) { 272293527Sdchagin if (error != 0) 273191896Sjamie return (error); 274293527Sdchagin if (len == 0 || osname[len - 1] != '\0') 275191896Sjamie return (EINVAL); 276191896Sjamie if (len > LINUX_MAX_UTSNAME) { 277191896Sjamie vfs_opterror(opts, "linux.osname too long"); 278191896Sjamie return (ENAMETOOLONG); 279191896Sjamie } 280191896Sjamie } 281191896Sjamie error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len); 282191896Sjamie if (error != ENOENT) { 283293527Sdchagin if (error != 0) 284191896Sjamie return (error); 285293527Sdchagin if (len == 0 || osrelease[len - 1] != '\0') 286191896Sjamie return (EINVAL); 287191896Sjamie if (len > LINUX_MAX_UTSNAME) { 288191896Sjamie vfs_opterror(opts, "linux.osrelease too long"); 289191896Sjamie return (ENAMETOOLONG); 290191896Sjamie } 291192895Sjamie error = linux_map_osrel(osrelease, &osrel); 292192895Sjamie if (error != 0) { 293192895Sjamie vfs_opterror(opts, "linux.osrelease format error"); 294192895Sjamie return (error); 295192895Sjamie } 296191896Sjamie } 297191896Sjamie error = vfs_copyopt(opts, "linux.oss_version", &oss_version, 298191896Sjamie sizeof(oss_version)); 299235063Snetchild 300235063Snetchild if (error == ENOENT) 301235063Snetchild error = 0; 302235063Snetchild return (error); 303191896Sjamie} 304191896Sjamie 305191896Sjamiestatic int 306191896Sjamielinux_prison_set(void *obj, void *data) 307191896Sjamie{ 308191896Sjamie struct linux_prison *lpr; 309191896Sjamie struct prison *pr = obj; 310191896Sjamie struct vfsoptlist *opts = data; 311191896Sjamie char *osname, *osrelease; 312195870Sjamie int error, gotversion, jsys, len, oss_version; 313191896Sjamie 314191896Sjamie /* Set the parameters, which should be correct. */ 315195870Sjamie error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)); 316195870Sjamie if (error == ENOENT) 317195870Sjamie jsys = -1; 318191896Sjamie error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len); 319191896Sjamie if (error == ENOENT) 320191896Sjamie osname = NULL; 321191896Sjamie else 322195870Sjamie jsys = JAIL_SYS_NEW; 323191896Sjamie error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len); 324191896Sjamie if (error == ENOENT) 325191896Sjamie osrelease = NULL; 326191896Sjamie else 327195870Sjamie jsys = JAIL_SYS_NEW; 328191896Sjamie error = vfs_copyopt(opts, "linux.oss_version", &oss_version, 329191896Sjamie sizeof(oss_version)); 330195870Sjamie if (error == ENOENT) 331195870Sjamie gotversion = 0; 332195870Sjamie else { 333195870Sjamie gotversion = 1; 334195870Sjamie jsys = JAIL_SYS_NEW; 335195870Sjamie } 336195870Sjamie switch (jsys) { 337195870Sjamie case JAIL_SYS_INHERIT: 338195870Sjamie /* "linux=inherit": inherit the parent's Linux info. */ 339191896Sjamie mtx_lock(&pr->pr_mtx); 340191896Sjamie osd_jail_del(pr, linux_osd_jail_slot); 341191896Sjamie mtx_unlock(&pr->pr_mtx); 342195870Sjamie break; 343195870Sjamie case JAIL_SYS_NEW: 344112206Sjhb /* 345195870Sjamie * "linux=new" or "linux.*": 346191896Sjamie * the prison gets its own Linux info. 347112206Sjhb */ 348191896Sjamie error = linux_alloc_prison(pr, &lpr); 349191896Sjamie if (error) { 350191896Sjamie mtx_unlock(&pr->pr_mtx); 351191896Sjamie return (error); 352191896Sjamie } 353191896Sjamie if (osrelease) { 354191972Sdchagin error = linux_map_osrel(osrelease, &lpr->pr_osrel); 355191972Sdchagin if (error) { 356191972Sdchagin mtx_unlock(&pr->pr_mtx); 357191972Sdchagin return (error); 358191972Sdchagin } 359191896Sjamie strlcpy(lpr->pr_osrelease, osrelease, 360191896Sjamie LINUX_MAX_UTSNAME); 361191896Sjamie } 362191972Sdchagin if (osname) 363191972Sdchagin strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME); 364191896Sjamie if (gotversion) 365191896Sjamie lpr->pr_oss_version = oss_version; 36687275Srwatson mtx_unlock(&pr->pr_mtx); 36750465Smarcel } 368235063Snetchild 369191896Sjamie return (0); 37050465Smarcel} 37150465Smarcel 372195870SjamieSYSCTL_JAIL_PARAM_SYS_NODE(linux, CTLFLAG_RW, "Jail Linux parameters"); 373191896SjamieSYSCTL_JAIL_PARAM_STRING(_linux, osname, CTLFLAG_RW, LINUX_MAX_UTSNAME, 374191896Sjamie "Jail Linux kernel OS name"); 375191896SjamieSYSCTL_JAIL_PARAM_STRING(_linux, osrelease, CTLFLAG_RW, LINUX_MAX_UTSNAME, 376191896Sjamie "Jail Linux kernel OS release"); 377191896SjamieSYSCTL_JAIL_PARAM(_linux, oss_version, CTLTYPE_INT | CTLFLAG_RW, 378191896Sjamie "I", "Jail Linux OSS version"); 379191896Sjamie 380191896Sjamiestatic int 381191896Sjamielinux_prison_get(void *obj, void *data) 382191896Sjamie{ 383191896Sjamie struct linux_prison *lpr; 384192895Sjamie struct prison *ppr; 385191896Sjamie struct prison *pr = obj; 386191896Sjamie struct vfsoptlist *opts = data; 387191896Sjamie int error, i; 388191896Sjamie 389192895Sjamie static int version0; 390192895Sjamie 391192895Sjamie /* See if this prison is the one with the Linux info. */ 392192895Sjamie lpr = linux_find_prison(pr, &ppr); 393195870Sjamie i = (ppr == pr) ? JAIL_SYS_NEW : JAIL_SYS_INHERIT; 394191896Sjamie error = vfs_setopt(opts, "linux", &i, sizeof(i)); 395293527Sdchagin if (error != 0 && error != ENOENT) 396293527Sdchagin goto done; 397192895Sjamie if (i) { 398195870Sjamie error = vfs_setopts(opts, "linux.osname", lpr->pr_osname); 399293527Sdchagin if (error != 0 && error != ENOENT) 400293527Sdchagin goto done; 401195870Sjamie error = vfs_setopts(opts, "linux.osrelease", lpr->pr_osrelease); 402293527Sdchagin if (error != 0 && error != ENOENT) 403293527Sdchagin goto done; 404195870Sjamie error = vfs_setopt(opts, "linux.oss_version", 405195870Sjamie &lpr->pr_oss_version, sizeof(lpr->pr_oss_version)); 406293527Sdchagin if (error != 0 && error != ENOENT) 407293527Sdchagin goto done; 408195870Sjamie } else { 409192895Sjamie /* 410192895Sjamie * If this prison is inheriting its Linux info, report 411192895Sjamie * empty/zero parameters. 412192895Sjamie */ 413192895Sjamie error = vfs_setopts(opts, "linux.osname", ""); 414293527Sdchagin if (error != 0 && error != ENOENT) 415293527Sdchagin goto done; 416192895Sjamie error = vfs_setopts(opts, "linux.osrelease", ""); 417293527Sdchagin if (error != 0 && error != ENOENT) 418293527Sdchagin goto done; 419192895Sjamie error = vfs_setopt(opts, "linux.oss_version", &version0, 420192895Sjamie sizeof(lpr->pr_oss_version)); 421293527Sdchagin if (error != 0 && error != ENOENT) 422293527Sdchagin goto done; 423191896Sjamie } 424191896Sjamie error = 0; 425191896Sjamie 426191896Sjamie done: 427192895Sjamie mtx_unlock(&ppr->pr_mtx); 428235063Snetchild 429191896Sjamie return (error); 430191896Sjamie} 431191896Sjamie 432191896Sjamiestatic void 433191896Sjamielinux_prison_destructor(void *data) 434191896Sjamie{ 435191896Sjamie 436191896Sjamie free(data, M_PRISON); 437191896Sjamie} 438191896Sjamie 43987275Srwatsonvoid 440191896Sjamielinux_osd_jail_register(void) 44150465Smarcel{ 442191896Sjamie struct prison *pr; 443191896Sjamie osd_method_t methods[PR_MAXMETHOD] = { 444191896Sjamie [PR_METHOD_CREATE] = linux_prison_create, 445191896Sjamie [PR_METHOD_GET] = linux_prison_get, 446191896Sjamie [PR_METHOD_SET] = linux_prison_set, 447191896Sjamie [PR_METHOD_CHECK] = linux_prison_check 448191896Sjamie }; 44950465Smarcel 450191896Sjamie linux_osd_jail_slot = 451191896Sjamie osd_jail_register(linux_prison_destructor, methods); 452191896Sjamie if (linux_osd_jail_slot > 0) { 453191896Sjamie /* Copy the system linux info to any current prisons. */ 454191896Sjamie sx_xlock(&allprison_lock); 455192895Sjamie TAILQ_FOREACH(pr, &allprison, pr_list) 456191896Sjamie (void)linux_alloc_prison(pr, NULL); 457191896Sjamie sx_xunlock(&allprison_lock); 45887275Srwatson } 459191896Sjamie} 46087275Srwatson 461191896Sjamievoid 462191896Sjamielinux_osd_jail_deregister(void) 463191896Sjamie{ 464191896Sjamie 465191896Sjamie if (linux_osd_jail_slot) 466191896Sjamie osd_jail_deregister(linux_osd_jail_slot); 46750465Smarcel} 46850465Smarcel 469191896Sjamievoid 470191896Sjamielinux_get_osname(struct thread *td, char *dst) 471191896Sjamie{ 472191896Sjamie struct prison *pr; 473191896Sjamie struct linux_prison *lpr; 474191896Sjamie 475192895Sjamie lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 476192895Sjamie bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME); 477192895Sjamie mtx_unlock(&pr->pr_mtx); 478191896Sjamie} 479191896Sjamie 480219668Snetchildstatic int 481112206Sjhblinux_set_osname(struct thread *td, char *osname) 48250465Smarcel{ 483112206Sjhb struct prison *pr; 484112206Sjhb struct linux_prison *lpr; 48550465Smarcel 486192895Sjamie lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 487192895Sjamie strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME); 488192895Sjamie mtx_unlock(&pr->pr_mtx); 489235063Snetchild 49050465Smarcel return (0); 49150465Smarcel} 49250465Smarcel 49387275Srwatsonvoid 494112206Sjhblinux_get_osrelease(struct thread *td, char *dst) 49550465Smarcel{ 496191896Sjamie struct prison *pr; 49787275Srwatson struct linux_prison *lpr; 49850465Smarcel 499192895Sjamie lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 500192895Sjamie bcopy(lpr->pr_osrelease, dst, LINUX_MAX_UTSNAME); 501192895Sjamie mtx_unlock(&pr->pr_mtx); 50250465Smarcel} 50350465Smarcel 50450465Smarcelint 505191972Sdchaginlinux_kernver(struct thread *td) 506165687Snetchild{ 507165687Snetchild struct prison *pr; 508165687Snetchild struct linux_prison *lpr; 509191972Sdchagin int osrel; 510165687Snetchild 511192895Sjamie lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 512192895Sjamie osrel = lpr->pr_osrel; 513192895Sjamie mtx_unlock(&pr->pr_mtx); 514235063Snetchild 515191972Sdchagin return (osrel); 516165687Snetchild} 517165687Snetchild 518219668Snetchildstatic int 519112206Sjhblinux_set_osrelease(struct thread *td, char *osrelease) 52050465Smarcel{ 521112206Sjhb struct prison *pr; 522112206Sjhb struct linux_prison *lpr; 523191972Sdchagin int error; 52450465Smarcel 525192895Sjamie lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 526192895Sjamie error = linux_map_osrel(osrelease, &lpr->pr_osrel); 527192895Sjamie if (error == 0) 528191896Sjamie strlcpy(lpr->pr_osrelease, osrelease, LINUX_MAX_UTSNAME); 529192895Sjamie mtx_unlock(&pr->pr_mtx); 530235063Snetchild 531192895Sjamie return (error); 53250465Smarcel} 53350465Smarcel 53450465Smarcelint 535112206Sjhblinux_get_oss_version(struct thread *td) 53650465Smarcel{ 537191896Sjamie struct prison *pr; 538191896Sjamie struct linux_prison *lpr; 53987275Srwatson int version; 54050465Smarcel 541192895Sjamie lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 542192895Sjamie version = lpr->pr_oss_version; 543192895Sjamie mtx_unlock(&pr->pr_mtx); 544235063Snetchild 54587275Srwatson return (version); 54650465Smarcel} 54750465Smarcel 548219668Snetchildstatic int 549112206Sjhblinux_set_oss_version(struct thread *td, int oss_version) 55050465Smarcel{ 551112206Sjhb struct prison *pr; 552112206Sjhb struct linux_prison *lpr; 55350465Smarcel 554192895Sjamie lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 555192895Sjamie lpr->pr_oss_version = oss_version; 556192895Sjamie mtx_unlock(&pr->pr_mtx); 557235063Snetchild 55850465Smarcel return (0); 55950465Smarcel} 560