From 9ce6c13ee8f8c304273fbbdef2e6fc6b3b038826 Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Tue, 14 Oct 2003 00:21:24 +0000 Subject: [PATCH] initial checkin git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/branches/SYSCALL_SWITCH@114 94cd875c-1c1d-0410-91d2-eb244daf1a30 --- util-vserver/lib/syscall-compat.hc | 66 ++++++++++ util-vserver/lib/syscall-legacy.hc | 236 ++++++++++++++++++++++++++++++++++++ util-vserver/lib/virtual-inc.h | 28 +++++ util-vserver/lib/virtual.h | 59 +++++++++ util-vserver/lib/vserver-internal.h | 53 ++++++++ 5 files changed, 442 insertions(+) create mode 100644 util-vserver/lib/syscall-compat.hc create mode 100644 util-vserver/lib/syscall-legacy.hc create mode 100644 util-vserver/lib/virtual-inc.h create mode 100644 util-vserver/lib/virtual.h create mode 100644 util-vserver/lib/vserver-internal.h diff --git a/util-vserver/lib/syscall-compat.hc b/util-vserver/lib/syscall-compat.hc new file mode 100644 index 0000000..899932b --- /dev/null +++ b/util-vserver/lib/syscall-compat.hc @@ -0,0 +1,66 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2003 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "compat.h" +#include "vserver.h" +#include "vserver-internal.h" + +#include + +static inline ALWAYSINLINE int +vc_new_s_context_compat(ctx_t ctx, unsigned int remove_cap, unsigned int flags) +{ + struct vcmd_new_s_context_v1 msg = { + .remove_cap = remove_cap, + .flags = flags + }; + + return sys_virtual_context(VC_CMD(COMPAT, 1, 1), ctx, &msg); +} + +static inline ALWAYSINLINE int +vc_set_ipv4root_compat(uint32_t bcast, size_t nb, struct vc_ip_mask_pair const *ips) +{ + struct vcmd_set_ipv4root_v3 msg = { + .broadcast = bcast + }; + size_t i; + + if (nb>=NB_IPV4ROOT) { + errno = -EINVAL; + return -1; + } + + for (i=0; i +// based on syscall.cc by Jacques Gelinas +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/* + This tells the system call number for new_s_context and set_ipv4root + using /proc/self/status. This helps until the vserver project is + included officially in the kernel (and has its own syscall). + + We rely on /proc/self/status to find the syscall number. + + If it is not there, we rely on adm/unistd.h. + + If this file does not have those system calls (not a patched kernel source) + we rely on static values in this file. +*/ +#include +#include +#include +#include +#include +#include + +// Here is the trick. We keep a copy of the define, then undef it +// and then later, we try to locate the value reading /proc/self/status +// If this fails, we have the old preserved copy. +static int def_NR_set_ipv4root = 274; +#undef __NR_set_ipv4root + +static int __NR_set_ipv4root_rev0; +static int __NR_set_ipv4root_rev1; +static int __NR_set_ipv4root_rev2; +static int __NR_set_ipv4root_rev3; +static int rev_ipv4root=0; + + +static _syscall1(int, set_ipv4root_rev0, unsigned long, ip) +static _syscall2(int, set_ipv4root_rev1, unsigned long, ip, unsigned long, bcast) +static _syscall3(int, set_ipv4root_rev2, unsigned long *, ip, int, nb, unsigned long, bcast) +static _syscall4(int, set_ipv4root_rev3, unsigned long *, ip, int, nb, unsigned long, bcast, unsigned long *, mask) + +static int def_NR_new_s_context = 273; +#undef __NR_new_s_context +static int __NR_new_s_context_rev0; + //static int __NR_new_s_context_rev1; +static int rev_s_context=0; + +static _syscall3(int, new_s_context_rev0, int, newctx, int, remove_cap, int, flags) + //static _syscall4(int, new_s_context_rev1, int, nbctx, int *, ctxs, int, remove_cap, int, flags) + +#if 0 +#undef __NR_set_ctxlimit +static int __NR_set_ctxlimit=-1; +static int rev_set_ctxlimit=-1; + +static _syscall2 (int, set_ctxlimit, int, resource, long, limit) +#endif + +#undef __NR_chrootsafe +static int __NR_chrootsafe=-1; +static int rev_chrootsafe=-1; + +static _syscall1 (int, chrootsafe, const char *, dir) + +static void init() +{ + static int is_init = 0; + if (!is_init){ + FILE *fin = fopen ("/proc/self/status","r"); + __NR_set_ipv4root_rev0 = def_NR_set_ipv4root; + __NR_set_ipv4root_rev1 = def_NR_set_ipv4root; + __NR_set_ipv4root_rev2 = def_NR_set_ipv4root; + __NR_set_ipv4root_rev3 = def_NR_set_ipv4root; + __NR_new_s_context_rev0 = def_NR_new_s_context; + //__NR_new_s_context_rev1 = def_NR_new_s_context; + if (fin != NULL){ + char line[100]; + while (fgets(line,sizeof(line)-1,fin)!=NULL){ + int num; + char title[100],rev[100]; + rev[0] = '\0'; + if (sscanf(line,"%s %d %s",title,&num,rev)>=2){ + if (strcmp(title,"__NR_set_ipv4root:")==0){ + __NR_set_ipv4root_rev0 = num; + __NR_set_ipv4root_rev1 = num; + __NR_set_ipv4root_rev2 = num; + __NR_set_ipv4root_rev3 = num; + if (strncmp(rev,"rev",3)==0){ + rev_ipv4root = atoi(rev+3); + } +#if 0 + }else if (strcmp(title,"__NR_set_ctxlimit:")==0){ + __NR_set_ctxlimit = num; + if (strncmp(rev,"rev",3)==0){ + rev_set_ctxlimit = atoi(rev+3); + } +#endif + }else if (strcmp(title,"__NR_chrootsafe:")==0){ + __NR_chrootsafe = num; + if (strncmp(rev,"rev",3)==0){ + rev_chrootsafe = atoi(rev+3); + } + }else if (strcmp(title,"__NR_new_s_context:")==0){ + __NR_new_s_context_rev0 = num; + //__NR_new_s_context_rev1 = num; + if (strncmp(rev,"rev",3)==0){ + rev_s_context = atoi(rev+3); + } + } + } + } + fclose (fin); + } + is_init = 1; + } +} + +void vc_init_legacy() +{ + init(); +} + +static ALWAYSINLINE int +vc_new_s_context_legacy(int ctx, int remove_cap, int flags) +{ + int ret = -1; + init(); + if (rev_s_context == 0){ + return new_s_context_rev0(ctx, remove_cap, flags); + }else{ + errno = -ENOSYS; + ret = -1; + } + return ret; +} + +static ALWAYSINLINE int +vc_set_ipv4root_legacy_internal ( + unsigned long ip[], + int nb, + unsigned long bcast, + unsigned long mask[]) +{ + init(); + if (rev_ipv4root == 0){ + if (nb > 1){ + fprintf (stderr,"set_ipv4root: Several IP number specified, but this kernel only supports one. Ignored\n"); + } + return set_ipv4root_rev0 (ip[0]); + }else if (rev_ipv4root == 1){ + if (nb > 1){ + fprintf (stderr,"set_ipv4root: Several IP number specified, but this kernel only supports one. Ignored\n"); + } + return set_ipv4root_rev1 (ip[0],bcast); + }else if (rev_ipv4root == 2){ + return set_ipv4root_rev2 (ip,nb,bcast); + }else if (rev_ipv4root == 3){ + return set_ipv4root_rev3 (ip,nb,bcast,mask); + } + errno = EINVAL; + return -1; +} + +static ALWAYSINLINE int +vc_set_ipv4root_legacy(uint32_t bcast, size_t nb, struct vc_ip_mask_pair const *ips) +{ + unsigned long ip[nb]; + unsigned long mask[nb]; + size_t i; + + for (i=0; i +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifndef H_VSERVER_SYSCALL_VIRTUAL_INC_H +#define H_VSERVER_SYSCALL_VIRTUAL_INC_H + +#ifdef HAVE_LINUX_VIRTUAL_H +# include +#else +# include "virtual.h" +#endif + +#endif // H_VSERVER_SYSCALL_VIRTUAL_INC_H diff --git a/util-vserver/lib/virtual.h b/util-vserver/lib/virtual.h new file mode 100644 index 0000000..57d74bf --- /dev/null +++ b/util-vserver/lib/virtual.h @@ -0,0 +1,59 @@ +#ifndef _LINUX_VIRTUAL_H +#define _LINUX_VIRTUAL_H + +#include + +#define VC_CATEGORY(c) (((c) >> 24) & 0x3F) +#define VC_COMMAND(c) (((c) >> 16) & 0xFF) +#define VC_VERSION(c) ((c) & 0xFFF) + +#define VC_CMD(c,i,v) ((((VC_CAT_ ## c) & 0x3F) << 24) \ + | (((i) & 0xFF) << 16) | ((v) & 0xFFF)) + +#define VC_CAT_VERSION 0 +#define VC_CAT_PROCESS 1 +#define VC_CAT_MEMORY 2 +#define VC_CAT_NETWORK 3 + +#define VC_CAT_LIMITS 8 +#define VC_CAT_QUOTA 9 + +#define VC_CAT_OTHER 62 +#define VC_CAT_COMPAT 63 + +/* interface version */ + + //#define VC_VERSION 0x00010000 + + + +/* query version */ + +#define VCMD_get_version VC_CMD(VERSION, 0, 0) + + +/* compatibiliy vserver commands */ + +#define VCMD_new_s_context VC_CMD(COMPAT, 1, 1) +#define VCMD_set_ipv4root VC_CMD(COMPAT, 2, 3) + +/* compatibiliy vserver arguments */ + +struct vcmd_new_s_context_v1 { + uint32_t remove_cap; + uint32_t flags; +}; + +#define NB_IPV4ROOT 16 + +struct vcmd_set_ipv4root_v3 { + /* number of pairs in id */ + uint32_t broadcast; + struct { + uint32_t ip; + uint32_t mask; + } ip_mask_pair[NB_IPV4ROOT]; +}; + + +#endif /* _LINUX_VIRTUAL_H */ diff --git a/util-vserver/lib/vserver-internal.h b/util-vserver/lib/vserver-internal.h new file mode 100644 index 0000000..cac969e --- /dev/null +++ b/util-vserver/lib/vserver-internal.h @@ -0,0 +1,53 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2003 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifndef H_VSERVER_SYSCALL_INTERNAL_H +#define H_VSERVER_SYSCALL_INTERNAL_H + +#include +#include +#include +#include +#include + +#ifndef __NR_sys_virtual_context +# define __NR_sys_virtual_context 273 +#endif + +#ifndef NDEBUG +static ALWAYSINLINE UNUSED void +vc_tell_unsafe_chroot() +{ + static int flag = -1; + if (flag==-1) { + char const * const e = getenv("VC_TELL_UNSAFE_CHROOT"); + flag = e ? atoi(e) : 0; + flag = flag ? 1 : 0; + } + + if (flag) write(2, "Unsafe chroot() used\n", 23); +} +#else +static ALWAYSINLINE UNUSED void vc_tell_unsafe_chroot() {} +#endif + +static _syscall3(int, sys_virtual_context, + uint32_t, cmd, uint32_t, id, void *, data) + + +#endif // H_VSERVER_SYSCALL_INTERNAL_H -- 1.8.1.5