From owner-svn-src-all@freebsd.org Tue Mar 7 17:07:17 2017 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id E98D5D02F71; Tue, 7 Mar 2017 17:07:17 +0000 (UTC) (envelope-from dchagin@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id AE18711FF; Tue, 7 Mar 2017 17:07:17 +0000 (UTC) (envelope-from dchagin@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v27H7GNo058247; Tue, 7 Mar 2017 17:07:16 GMT (envelope-from dchagin@FreeBSD.org) Received: (from dchagin@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v27H7GVL058242; Tue, 7 Mar 2017 17:07:16 GMT (envelope-from dchagin@FreeBSD.org) Message-Id: <201703071707.v27H7GVL058242@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: dchagin set sender to dchagin@FreeBSD.org using -f From: Dmitry Chagin Date: Tue, 7 Mar 2017 17:07:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r314866 - in head/sys: amd64/linux amd64/linux32 compat/linux i386/linux X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 Mar 2017 17:07:18 -0000 Author: dchagin Date: Tue Mar 7 17:07:16 2017 New Revision: 314866 URL: https://svnweb.freebsd.org/changeset/base/314866 Log: Reduce code duplication between MD Linux code by moving SYSV IPC 64-bit related struct definitions out into the MI path. Invert the native ipc structs to the Linux ipc structs convesion logic. Since 64-bit variant of ipc structs has more precision convert native ipc structs to the 64-bit Linux ipc structs and then truncate 64-bit values into the non 64-bit if needed. Unlike Linux, return EOVERFLOW if the values do not fit. Fix SYSV IPC for 64-bit Linuxulator which never sets IPC_64 bit. MFC after: 1 month Added: head/sys/compat/linux/linux_ipc64.h - copied, changed from r314865, head/sys/i386/linux/linux_ipc64.h Deleted: head/sys/amd64/linux/linux_ipc64.h head/sys/amd64/linux32/linux32_ipc64.h head/sys/i386/linux/linux_ipc64.h Modified: head/sys/amd64/linux/linux.h head/sys/amd64/linux32/linux.h head/sys/compat/linux/linux_ipc.c head/sys/i386/linux/linux.h Modified: head/sys/amd64/linux/linux.h ============================================================================== --- head/sys/amd64/linux/linux.h Tue Mar 7 16:09:37 2017 (r314865) +++ head/sys/amd64/linux/linux.h Tue Mar 7 17:07:16 2017 (r314866) @@ -69,7 +69,9 @@ typedef l_long l_clock_t; typedef l_int l_daddr_t; typedef l_ulong l_dev_t; typedef l_uint l_gid_t; +typedef l_ushort l_gid16_t; typedef l_uint l_uid_t; +typedef l_ushort l_uid16_t; typedef l_ulong l_ino_t; typedef l_int l_key_t; typedef l_long l_loff_t; @@ -381,16 +383,6 @@ union l_semun { l_uintptr_t __pad; }; -struct l_ipc_perm { - l_key_t key; - l_uid_t uid; - l_gid_t gid; - l_uid_t cuid; - l_gid_t cgid; - l_ushort mode; - l_ushort seq; -}; - /* * Socket defines */ Modified: head/sys/amd64/linux32/linux.h ============================================================================== --- head/sys/amd64/linux32/linux.h Tue Mar 7 16:09:37 2017 (r314865) +++ head/sys/amd64/linux32/linux.h Tue Mar 7 17:07:16 2017 (r314866) @@ -474,16 +474,6 @@ union l_semun { l_uintptr_t __pad; } __packed; -struct l_ipc_perm { - l_key_t key; - l_uid16_t uid; - l_gid16_t gid; - l_uid16_t cuid; - l_gid16_t cgid; - l_ushort mode; - l_ushort seq; -}; - /* * Socket defines */ Modified: head/sys/compat/linux/linux_ipc.c ============================================================================== --- head/sys/compat/linux/linux_ipc.c Tue Mar 7 16:09:37 2017 (r314865) +++ head/sys/compat/linux/linux_ipc.c Tue Mar 7 17:07:16 2017 (r314866) @@ -44,15 +44,27 @@ __FBSDID("$FreeBSD$"); #ifdef COMPAT_LINUX32 #include #include -#include #else #include #include -#include #endif #include +#include #include +/* + * old, pre 2.4 kernel + */ +struct l_ipc_perm { + l_key_t key; + l_uid16_t uid; + l_gid16_t gid; + l_uid16_t cuid; + l_gid16_t cgid; + l_ushort mode; + l_ushort seq; +}; + struct l_seminfo { l_int semmap; l_int semmni; @@ -95,7 +107,7 @@ struct l_msginfo { }; static void -bsd_to_linux_shminfo( struct shminfo *bpp, struct l_shminfo *lpp) +bsd_to_linux_shminfo( struct shminfo *bpp, struct l_shminfo64 *lpp) { lpp->shmmax = bpp->shmmax; @@ -109,16 +121,16 @@ static void bsd_to_linux_shm_info( struct shm_info *bpp, struct l_shm_info *lpp) { - lpp->used_ids = bpp->used_ids ; - lpp->shm_tot = bpp->shm_tot ; - lpp->shm_rss = bpp->shm_rss ; - lpp->shm_swp = bpp->shm_swp ; - lpp->swap_attempts = bpp->swap_attempts ; - lpp->swap_successes = bpp->swap_successes ; + lpp->used_ids = bpp->used_ids; + lpp->shm_tot = bpp->shm_tot; + lpp->shm_rss = bpp->shm_rss; + lpp->shm_swp = bpp->shm_swp; + lpp->swap_attempts = bpp->swap_attempts; + lpp->swap_successes = bpp->swap_successes; } static void -linux_to_bsd_ipc_perm(struct l_ipc_perm *lpp, struct ipc_perm *bpp) +linux_to_bsd_ipc_perm(struct l_ipc64_perm *lpp, struct ipc_perm *bpp) { bpp->key = lpp->key; @@ -131,7 +143,7 @@ linux_to_bsd_ipc_perm(struct l_ipc_perm } static void -bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc_perm *lpp) +bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc64_perm *lpp) { lpp->key = bpp->key; @@ -185,29 +197,27 @@ struct l_shmid_ds { }; static void -linux_to_bsd_semid_ds(struct l_semid_ds *lsp, struct semid_ds *bsp) +linux_to_bsd_semid_ds(struct l_semid64_ds *lsp, struct semid_ds *bsp) { linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm); bsp->sem_otime = lsp->sem_otime; bsp->sem_ctime = lsp->sem_ctime; bsp->sem_nsems = lsp->sem_nsems; - bsp->sem_base = PTRIN(lsp->sem_base); } static void -bsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid_ds *lsp) +bsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid64_ds *lsp) { bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm); lsp->sem_otime = bsp->sem_otime; lsp->sem_ctime = bsp->sem_ctime; lsp->sem_nsems = bsp->sem_nsems; - lsp->sem_base = PTROUT(bsp->sem_base); } static void -linux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp) +linux_to_bsd_shmid_ds(struct l_shmid64_ds *lsp, struct shmid_ds *bsp) { linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm); @@ -221,28 +231,21 @@ linux_to_bsd_shmid_ds(struct l_shmid_ds } static void -bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp) +bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid64_ds *lsp) { bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); - if (bsp->shm_segsz > INT_MAX) - lsp->shm_segsz = INT_MAX; - else - lsp->shm_segsz = bsp->shm_segsz; + lsp->shm_segsz = bsp->shm_segsz; lsp->shm_lpid = bsp->shm_lpid; lsp->shm_cpid = bsp->shm_cpid; - if (bsp->shm_nattch > SHRT_MAX) - lsp->shm_nattch = SHRT_MAX; - else - lsp->shm_nattch = bsp->shm_nattch; + lsp->shm_nattch = bsp->shm_nattch; lsp->shm_atime = bsp->shm_atime; lsp->shm_dtime = bsp->shm_dtime; lsp->shm_ctime = bsp->shm_ctime; - lsp->private3 = 0; } static void -linux_to_bsd_msqid_ds(struct l_msqid_ds *lsp, struct msqid_ds *bsp) +linux_to_bsd_msqid_ds(struct l_msqid64_ds *lsp, struct msqid_ds *bsp) { linux_to_bsd_ipc_perm(&lsp->msg_perm, &bsp->msg_perm); @@ -257,7 +260,7 @@ linux_to_bsd_msqid_ds(struct l_msqid_ds } static void -bsd_to_linux_msqid_ds(struct msqid_ds *bsp, struct l_msqid_ds *lsp) +bsd_to_linux_msqid_ds(struct msqid_ds *bsp, struct l_msqid64_ds *lsp) { bsd_to_linux_ipc_perm(&bsp->msg_perm, &lsp->msg_perm); @@ -271,11 +274,10 @@ bsd_to_linux_msqid_ds(struct msqid_ds *b lsp->msg_ctime = bsp->msg_ctime; } -static void -linux_ipc_perm_to_ipc64_perm(struct l_ipc_perm *in, struct l_ipc64_perm *out) +static int +linux_ipc64_perm_to_ipc_perm(struct l_ipc64_perm *in, struct l_ipc_perm *out) { - /* XXX: do we really need to do something here? */ out->key = in->key; out->uid = in->uid; out->gid = in->gid; @@ -283,186 +285,222 @@ linux_ipc_perm_to_ipc64_perm(struct l_ip out->cgid = in->cgid; out->mode = in->mode; out->seq = in->seq; + + /* Linux does not check overflow */ + if (out->uid != in->uid || out->gid != in->gid || + out->cuid != in->cuid || out->cgid != in->cgid || + out->mode != in->mode) + return (EOVERFLOW); + else + return (0); } static int -linux_msqid_pullup(l_int ver, struct l_msqid_ds *linux_msqid, caddr_t uaddr) +linux_msqid_pullup(l_int ver, struct l_msqid64_ds *linux_msqid64, caddr_t uaddr) { - struct l_msqid64_ds linux_msqid64; + struct l_msqid_ds linux_msqid; int error; - if (ver == LINUX_IPC_64) { - error = copyin(uaddr, &linux_msqid64, sizeof(linux_msqid64)); + if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64)) + return (copyin(uaddr, linux_msqid64, sizeof(*linux_msqid64))); + else { + error = copyin(uaddr, &linux_msqid, sizeof(linux_msqid)); if (error != 0) return (error); - bzero(linux_msqid, sizeof(*linux_msqid)); - - linux_msqid->msg_perm.uid = linux_msqid64.msg_perm.uid; - linux_msqid->msg_perm.gid = linux_msqid64.msg_perm.gid; - linux_msqid->msg_perm.mode = linux_msqid64.msg_perm.mode; + bzero(linux_msqid64, sizeof(*linux_msqid64)); - if (linux_msqid64.msg_qbytes > USHRT_MAX) - linux_msqid->msg_lqbytes = linux_msqid64.msg_qbytes; + linux_msqid64->msg_perm.uid = linux_msqid.msg_perm.uid; + linux_msqid64->msg_perm.gid = linux_msqid.msg_perm.gid; + linux_msqid64->msg_perm.mode = linux_msqid.msg_perm.mode; + if (linux_msqid.msg_qbytes == 0) + linux_msqid64->msg_qbytes = linux_msqid.msg_lqbytes; else - linux_msqid->msg_qbytes = linux_msqid64.msg_qbytes; - } else - error = copyin(uaddr, linux_msqid, sizeof(*linux_msqid)); - - return (error); + linux_msqid64->msg_qbytes = linux_msqid.msg_qbytes; + return (0); + } } static int -linux_msqid_pushdown(l_int ver, struct l_msqid_ds *linux_msqid, caddr_t uaddr) +linux_msqid_pushdown(l_int ver, struct l_msqid64_ds *linux_msqid64, caddr_t uaddr) { - struct l_msqid64_ds linux_msqid64; + struct l_msqid_ds linux_msqid; + int error; - if (ver == LINUX_IPC_64) { - bzero(&linux_msqid64, sizeof(linux_msqid64)); + if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64)) + return (copyout(linux_msqid64, uaddr, sizeof(*linux_msqid64))); + else { + bzero(&linux_msqid, sizeof(linux_msqid)); - linux_ipc_perm_to_ipc64_perm(&linux_msqid->msg_perm, - &linux_msqid64.msg_perm); + error = linux_ipc64_perm_to_ipc_perm(&linux_msqid64->msg_perm, + &linux_msqid.msg_perm); + if (error != 0) + return (error); - linux_msqid64.msg_stime = linux_msqid->msg_stime; - linux_msqid64.msg_rtime = linux_msqid->msg_rtime; - linux_msqid64.msg_ctime = linux_msqid->msg_ctime; + linux_msqid.msg_stime = linux_msqid64->msg_stime; + linux_msqid.msg_rtime = linux_msqid64->msg_rtime; + linux_msqid.msg_ctime = linux_msqid64->msg_ctime; - if (linux_msqid->msg_cbytes == 0) - linux_msqid64.msg_cbytes = linux_msqid->msg_lcbytes; + if (linux_msqid64->msg_cbytes > USHRT_MAX) + linux_msqid.msg_cbytes = USHRT_MAX; else - linux_msqid64.msg_cbytes = linux_msqid->msg_cbytes; - - linux_msqid64.msg_qnum = linux_msqid->msg_qnum; - - if (linux_msqid->msg_qbytes == 0) - linux_msqid64.msg_qbytes = linux_msqid->msg_lqbytes; + linux_msqid.msg_cbytes = linux_msqid64->msg_cbytes; + linux_msqid.msg_lcbytes = linux_msqid64->msg_cbytes; + if (linux_msqid64->msg_qnum > USHRT_MAX) + linux_msqid.msg_qnum = linux_msqid64->msg_qnum; else - linux_msqid64.msg_qbytes = linux_msqid->msg_qbytes; - - linux_msqid64.msg_lspid = linux_msqid->msg_lspid; - linux_msqid64.msg_lrpid = linux_msqid->msg_lrpid; + linux_msqid.msg_qnum = linux_msqid64->msg_qnum; + if (linux_msqid64->msg_qbytes > USHRT_MAX) + linux_msqid.msg_qbytes = linux_msqid64->msg_qbytes; + else + linux_msqid.msg_qbytes = linux_msqid64->msg_qbytes; + linux_msqid.msg_lqbytes = linux_msqid64->msg_qbytes; + linux_msqid.msg_lspid = linux_msqid64->msg_lspid; + linux_msqid.msg_lrpid = linux_msqid64->msg_lrpid; + + /* Linux does not check overflow */ + if (linux_msqid.msg_stime != linux_msqid64->msg_stime || + linux_msqid.msg_rtime != linux_msqid64->msg_rtime || + linux_msqid.msg_ctime != linux_msqid64->msg_ctime) + return (EOVERFLOW); - return (copyout(&linux_msqid64, uaddr, sizeof(linux_msqid64))); - } else - return (copyout(linux_msqid, uaddr, sizeof(*linux_msqid))); + return (copyout(&linux_msqid, uaddr, sizeof(linux_msqid))); + } } static int -linux_semid_pullup(l_int ver, struct l_semid_ds *linux_semid, caddr_t uaddr) +linux_semid_pullup(l_int ver, struct l_semid64_ds *linux_semid64, caddr_t uaddr) { - struct l_semid64_ds linux_semid64; + struct l_semid_ds linux_semid; int error; - if (ver == LINUX_IPC_64) { - error = copyin(uaddr, &linux_semid64, sizeof(linux_semid64)); + if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64)) + return (copyin(uaddr, linux_semid64, sizeof(*linux_semid64))); + else { + error = copyin(uaddr, &linux_semid, sizeof(linux_semid)); if (error != 0) return (error); - bzero(linux_semid, sizeof(*linux_semid)); - - linux_semid->sem_perm.uid = linux_semid64.sem_perm.uid; - linux_semid->sem_perm.gid = linux_semid64.sem_perm.gid; - linux_semid->sem_perm.mode = linux_semid64.sem_perm.mode; - } else - error = copyin(uaddr, linux_semid, sizeof(*linux_semid)); + bzero(linux_semid64, sizeof(*linux_semid64)); - return (error); + linux_semid64->sem_perm.uid = linux_semid.sem_perm.uid; + linux_semid64->sem_perm.gid = linux_semid.sem_perm.gid; + linux_semid64->sem_perm.mode = linux_semid.sem_perm.mode; + return (0); + } } static int -linux_semid_pushdown(l_int ver, struct l_semid_ds *linux_semid, caddr_t uaddr) +linux_semid_pushdown(l_int ver, struct l_semid64_ds *linux_semid64, caddr_t uaddr) { - struct l_semid64_ds linux_semid64; + struct l_semid_ds linux_semid; + int error; + + if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64)) + return (copyout(linux_semid64, uaddr, sizeof(*linux_semid64))); + else { + bzero(&linux_semid, sizeof(linux_semid)); + + error = linux_ipc64_perm_to_ipc_perm(&linux_semid64->sem_perm, + &linux_semid.sem_perm); + if (error != 0) + return (error); - if (ver == LINUX_IPC_64) { - bzero(&linux_semid64, sizeof(linux_semid64)); + linux_semid.sem_otime = linux_semid64->sem_otime; + linux_semid.sem_ctime = linux_semid64->sem_ctime; + linux_semid.sem_nsems = linux_semid64->sem_nsems; - linux_ipc_perm_to_ipc64_perm(&linux_semid->sem_perm, - &linux_semid64.sem_perm); + /* Linux does not check overflow */ + if (linux_semid.sem_otime != linux_semid64->sem_otime || + linux_semid.sem_ctime != linux_semid64->sem_ctime || + linux_semid.sem_nsems != linux_semid64->sem_nsems) + return (EOVERFLOW); - linux_semid64.sem_otime = linux_semid->sem_otime; - linux_semid64.sem_ctime = linux_semid->sem_ctime; - linux_semid64.sem_nsems = linux_semid->sem_nsems; - - return (copyout(&linux_semid64, uaddr, sizeof(linux_semid64))); - } else - return (copyout(linux_semid, uaddr, sizeof(*linux_semid))); + return (copyout(&linux_semid, uaddr, sizeof(linux_semid))); + } } static int -linux_shmid_pullup(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr) +linux_shmid_pullup(l_int ver, struct l_shmid64_ds *linux_shmid64, caddr_t uaddr) { - struct l_shmid64_ds linux_shmid64; + struct l_shmid_ds linux_shmid; int error; - if (ver == LINUX_IPC_64) { - error = copyin(uaddr, &linux_shmid64, sizeof(linux_shmid64)); + if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64)) + return (copyin(uaddr, linux_shmid64, sizeof(*linux_shmid64))); + else { + error = copyin(uaddr, &linux_shmid, sizeof(linux_shmid)); if (error != 0) return (error); - bzero(linux_shmid, sizeof(*linux_shmid)); + bzero(linux_shmid64, sizeof(*linux_shmid64)); - linux_shmid->shm_perm.uid = linux_shmid64.shm_perm.uid; - linux_shmid->shm_perm.gid = linux_shmid64.shm_perm.gid; - linux_shmid->shm_perm.mode = linux_shmid64.shm_perm.mode; - } else - error = copyin(uaddr, linux_shmid, sizeof(*linux_shmid)); - - return (error); + linux_shmid64->shm_perm.uid = linux_shmid.shm_perm.uid; + linux_shmid64->shm_perm.gid = linux_shmid.shm_perm.gid; + linux_shmid64->shm_perm.mode = linux_shmid.shm_perm.mode; + return (0); + } } static int -linux_shmid_pushdown(l_int ver, struct l_shmid_ds *linux_shmid, caddr_t uaddr) +linux_shmid_pushdown(l_int ver, struct l_shmid64_ds *linux_shmid64, caddr_t uaddr) { - struct l_shmid64_ds linux_shmid64; + struct l_shmid_ds linux_shmid; + int error; - /* - * XXX: This is backwards and loses information in shm_nattch - * and shm_segsz. We should probably either expose the BSD - * shmid structure directly and convert it to either the - * non-64 or 64 variant directly or the code should always - * convert to the 64 variant and then truncate values into the - * non-64 variant if needed since the 64 variant has more - * precision. - */ - if (ver == LINUX_IPC_64) { - bzero(&linux_shmid64, sizeof(linux_shmid64)); + if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64)) + return (copyout(linux_shmid64, uaddr, sizeof(*linux_shmid64))); + else { + bzero(&linux_shmid, sizeof(linux_shmid)); + + error = linux_ipc64_perm_to_ipc_perm(&linux_shmid64->shm_perm, + &linux_shmid.shm_perm); + if (error != 0) + return (error); - linux_ipc_perm_to_ipc64_perm(&linux_shmid->shm_perm, - &linux_shmid64.shm_perm); + linux_shmid.shm_segsz = linux_shmid64->shm_segsz; + linux_shmid.shm_atime = linux_shmid64->shm_atime; + linux_shmid.shm_dtime = linux_shmid64->shm_dtime; + linux_shmid.shm_ctime = linux_shmid64->shm_ctime; + linux_shmid.shm_cpid = linux_shmid64->shm_cpid; + linux_shmid.shm_lpid = linux_shmid64->shm_lpid; + linux_shmid.shm_nattch = linux_shmid64->shm_nattch; + + /* Linux does not check overflow */ + if (linux_shmid.shm_segsz != linux_shmid64->shm_segsz || + linux_shmid.shm_atime != linux_shmid64->shm_atime || + linux_shmid.shm_dtime != linux_shmid64->shm_dtime || + linux_shmid.shm_ctime != linux_shmid64->shm_ctime || + linux_shmid.shm_cpid != linux_shmid64->shm_cpid || + linux_shmid.shm_lpid != linux_shmid64->shm_lpid || + linux_shmid.shm_nattch != linux_shmid64->shm_nattch) + return (EOVERFLOW); - linux_shmid64.shm_segsz = linux_shmid->shm_segsz; - linux_shmid64.shm_atime = linux_shmid->shm_atime; - linux_shmid64.shm_dtime = linux_shmid->shm_dtime; - linux_shmid64.shm_ctime = linux_shmid->shm_ctime; - linux_shmid64.shm_cpid = linux_shmid->shm_cpid; - linux_shmid64.shm_lpid = linux_shmid->shm_lpid; - linux_shmid64.shm_nattch = linux_shmid->shm_nattch; - - return (copyout(&linux_shmid64, uaddr, sizeof(linux_shmid64))); - } else - return (copyout(linux_shmid, uaddr, sizeof(*linux_shmid))); + return (copyout(&linux_shmid, uaddr, sizeof(linux_shmid))); + } } static int -linux_shminfo_pushdown(l_int ver, struct l_shminfo *linux_shminfo, +linux_shminfo_pushdown(l_int ver, struct l_shminfo64 *linux_shminfo64, caddr_t uaddr) { - struct l_shminfo64 linux_shminfo64; + struct l_shminfo linux_shminfo; - if (ver == LINUX_IPC_64) { - bzero(&linux_shminfo64, sizeof(linux_shminfo64)); + if (ver == LINUX_IPC_64 || SV_CURPROC_FLAG(SV_LP64)) + return (copyout(linux_shminfo64, uaddr, + sizeof(*linux_shminfo64))); + else { + bzero(&linux_shminfo, sizeof(linux_shminfo)); + + linux_shminfo.shmmax = linux_shminfo64->shmmax; + linux_shminfo.shmmin = linux_shminfo64->shmmin; + linux_shminfo.shmmni = linux_shminfo64->shmmni; + linux_shminfo.shmseg = linux_shminfo64->shmseg; + linux_shminfo.shmall = linux_shminfo64->shmall; - linux_shminfo64.shmmax = linux_shminfo->shmmax; - linux_shminfo64.shmmin = linux_shminfo->shmmin; - linux_shminfo64.shmmni = linux_shminfo->shmmni; - linux_shminfo64.shmseg = linux_shminfo->shmseg; - linux_shminfo64.shmall = linux_shminfo->shmall; - - return (copyout(&linux_shminfo64, uaddr, - sizeof(linux_shminfo64))); - } else - return (copyout(linux_shminfo, uaddr, sizeof(*linux_shminfo))); + return (copyout(&linux_shminfo, uaddr, + sizeof(linux_shminfo))); + } } int @@ -500,7 +538,7 @@ linux_semget(struct thread *td, struct l int linux_semctl(struct thread *td, struct linux_semctl_args *args) { - struct l_semid_ds linux_semid; + struct l_semid64_ds linux_semid64; struct l_seminfo linux_seminfo; struct semid_ds semid; union semun semun; @@ -530,29 +568,35 @@ linux_semctl(struct thread *td, struct l case LINUX_IPC_SET: cmd = IPC_SET; error = linux_semid_pullup(args->cmd & LINUX_IPC_64, - &linux_semid, PTRIN(args->arg.buf)); + &linux_semid64, PTRIN(args->arg.buf)); if (error != 0) return (error); - linux_to_bsd_semid_ds(&linux_semid, &semid); + linux_to_bsd_semid_ds(&linux_semid64, &semid); semun.buf = &semid; return (kern_semctl(td, args->semid, args->semnum, cmd, &semun, td->td_retval)); case LINUX_IPC_STAT: + cmd = IPC_STAT; + semun.buf = &semid; + error = kern_semctl(td, args->semid, args->semnum, cmd, &semun, + &rval); + if (error != 0) + return (error); + bsd_to_linux_semid_ds(&semid, &linux_semid64); + return (linux_semid_pushdown(args->cmd & LINUX_IPC_64, + &linux_semid64, PTRIN(args->arg.buf))); case LINUX_SEM_STAT: - if ((args->cmd & ~LINUX_IPC_64) == LINUX_IPC_STAT) - cmd = IPC_STAT; - else - cmd = SEM_STAT; + cmd = SEM_STAT; semun.buf = &semid; error = kern_semctl(td, args->semid, args->semnum, cmd, &semun, &rval); if (error != 0) return (error); - bsd_to_linux_semid_ds(&semid, &linux_semid); + bsd_to_linux_semid_ds(&semid, &linux_semid64); error = linux_semid_pushdown(args->cmd & LINUX_IPC_64, - &linux_semid, PTRIN(args->arg.buf)); + &linux_semid64, PTRIN(args->arg.buf)); if (error == 0) - td->td_retval[0] = (cmd == SEM_STAT) ? rval : 0; + td->td_retval[0] = rval; return (error); case LINUX_IPC_INFO: case LINUX_SEM_INFO: @@ -575,15 +619,18 @@ linux_semctl(struct thread *td, struct l PTRIN(args->arg.buf), sizeof(linux_seminfo)); if (error != 0) return (error); + /* + * TODO: Linux return the last assigned id, not the semmni. + */ td->td_retval[0] = seminfo.semmni; - return (0); /* No need for __semctl call */ + return (0); case LINUX_GETALL: cmd = GETALL; - semun.val = args->arg.val; + semun.array = PTRIN(args->arg.array); break; case LINUX_SETALL: cmd = SETALL; - semun.val = args->arg.val; + semun.array = PTRIN(args->arg.array); break; default: linux_msg(td, "ipc type %d is not implemented", @@ -649,7 +696,7 @@ int linux_msgctl(struct thread *td, struct linux_msgctl_args *args) { int error, bsd_cmd; - struct l_msqid_ds linux_msqid; + struct l_msqid64_ds linux_msqid64; struct msqid_ds bsd_msqid; bsd_cmd = args->cmd & ~LINUX_IPC_64; @@ -689,10 +736,10 @@ linux_msgctl(struct thread *td, struct l case LINUX_IPC_SET: error = linux_msqid_pullup(args->cmd & LINUX_IPC_64, - &linux_msqid, PTRIN(args->buf)); + &linux_msqid64, PTRIN(args->buf)); if (error != 0) return (error); - linux_to_bsd_msqid_ds(&linux_msqid, &bsd_msqid); + linux_to_bsd_msqid_ds(&linux_msqid64, &bsd_msqid); break; case LINUX_IPC_RMID: @@ -705,14 +752,17 @@ linux_msgctl(struct thread *td, struct l } error = kern_msgctl(td, args->msqid, bsd_cmd, &bsd_msqid); - if (error != 0) + if (error != 0) { + if (bsd_cmd == LINUX_IPC_RMID && error == EACCES) + return (EPERM); if (bsd_cmd != LINUX_IPC_RMID || error != EINVAL) return (error); + } if (bsd_cmd == LINUX_IPC_STAT) { - bsd_to_linux_msqid_ds(&bsd_msqid, &linux_msqid); + bsd_to_linux_msqid_ds(&bsd_msqid, &linux_msqid64); return (linux_msqid_pushdown(args->cmd & LINUX_IPC_64, - &linux_msqid, PTRIN(args->buf))); + &linux_msqid64, PTRIN(args->buf))); } return (0); @@ -774,8 +824,8 @@ linux_shmget(struct thread *td, struct l int linux_shmctl(struct thread *td, struct linux_shmctl_args *args) { - struct l_shmid_ds linux_shmid; - struct l_shminfo linux_shminfo; + struct l_shmid64_ds linux_shmid64; + struct l_shminfo64 linux_shminfo64; struct l_shm_info linux_shm_info; struct shmid_ds bsd_shmid; int error; @@ -791,10 +841,10 @@ linux_shmctl(struct thread *td, struct l if (error != 0) return (error); - bsd_to_linux_shminfo(&bsd_shminfo, &linux_shminfo); + bsd_to_linux_shminfo(&bsd_shminfo, &linux_shminfo64); return (linux_shminfo_pushdown(args->cmd & LINUX_IPC_64, - &linux_shminfo, PTRIN(args->buf))); + &linux_shminfo64, PTRIN(args->buf))); } case LINUX_SHM_INFO: { @@ -819,10 +869,10 @@ linux_shmctl(struct thread *td, struct l if (error != 0) return (error); - bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); + bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid64); return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64, - &linux_shmid, PTRIN(args->buf))); + &linux_shmid64, PTRIN(args->buf))); case LINUX_SHM_STAT: /* Perform shmctl wanting removed segments lookup */ @@ -831,18 +881,18 @@ linux_shmctl(struct thread *td, struct l if (error != 0) return (error); - bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); + bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid64); return (linux_shmid_pushdown(args->cmd & LINUX_IPC_64, - &linux_shmid, PTRIN(args->buf))); + &linux_shmid64, PTRIN(args->buf))); case LINUX_IPC_SET: error = linux_shmid_pullup(args->cmd & LINUX_IPC_64, - &linux_shmid, PTRIN(args->buf)); + &linux_shmid64, PTRIN(args->buf)); if (error != 0) return (error); - linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); + linux_to_bsd_shmid_ds(&linux_shmid64, &bsd_shmid); /* Perform shmctl wanting removed segments lookup */ return (kern_shmctl(td, args->shmid, IPC_SET, @@ -855,10 +905,10 @@ linux_shmctl(struct thread *td, struct l buf = NULL; else { error = linux_shmid_pullup(args->cmd & LINUX_IPC_64, - &linux_shmid, PTRIN(args->buf)); + &linux_shmid64, PTRIN(args->buf)); if (error != 0) return (error); - linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); + linux_to_bsd_shmid_ds(&linux_shmid64, &bsd_shmid); buf = (void *)&bsd_shmid; } return (kern_shmctl(td, args->shmid, IPC_RMID, buf, NULL)); Copied and modified: head/sys/compat/linux/linux_ipc64.h (from r314865, head/sys/i386/linux/linux_ipc64.h) ============================================================================== --- head/sys/i386/linux/linux_ipc64.h Tue Mar 7 16:09:37 2017 (r314865, copy source) +++ head/sys/compat/linux/linux_ipc64.h Tue Mar 7 17:07:16 2017 (r314866) @@ -6,7 +6,7 @@ * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer + * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the @@ -28,19 +28,19 @@ * $FreeBSD$ */ -#ifndef _I386_LINUX_LINUX_IPC64_H_ -#define _I386_LINUX_LINUX_IPC64_H_ +#ifndef _LINUX_IPC64_H_ +#define _LINUX_IPC64_H_ /* - * The ipc64_perm structure for i386 architecture. + * The generic ipc64_perm structure. * Note extra padding because this structure is passed back and forth * between kernel and user space. * * Pad space is left for: - * - 32-bit mode_t and seq + * - 32-bit mode_t on architectures that only had 16 bit + * - 32-bit seq * - 2 miscellaneous 32-bit values */ - struct l_ipc64_perm { l_key_t key; @@ -49,7 +49,8 @@ struct l_ipc64_perm l_uid_t cuid; l_gid_t cgid; l_mode_t mode; - l_ushort __pad1; + /* pad if mode_t is ushort: */ + unsigned char __pad1[sizeof(l_int) - sizeof(l_mode_t)]; l_ushort seq; l_ushort __pad2; l_ulong __unused1; @@ -57,7 +58,7 @@ struct l_ipc64_perm }; /* - * The msqid64_ds structure for i386 architecture. + * The generic msqid64_ds structure fro x86 architecture. * Note extra padding because this structure is passed back and forth * between kernel and user space. * @@ -69,11 +70,17 @@ struct l_ipc64_perm struct l_msqid64_ds { struct l_ipc64_perm msg_perm; l_time_t msg_stime; /* last msgsnd time */ +#if !defined(__LP64__) || defined(COMPAT_LINUX32) l_ulong __unused1; +#endif l_time_t msg_rtime; /* last msgrcv time */ +#if !defined(__LP64__) || defined(COMPAT_LINUX32) l_ulong __unused2; +#endif l_time_t msg_ctime; /* last change time */ +#if !defined(__LP64__) || defined(COMPAT_LINUX32) l_ulong __unused3; +#endif l_ulong msg_cbytes; /* current number of bytes on queue */ l_ulong msg_qnum; /* number of messages in queue */ l_ulong msg_qbytes; /* max number of bytes on queue */ @@ -84,7 +91,7 @@ struct l_msqid64_ds { }; /* - * The semid64_ds structure for i386 architecture. + * The generic semid64_ds structure for x86 architecture. * Note extra padding because this structure is passed back and forth * between kernel and user space. * @@ -105,7 +112,7 @@ struct l_semid64_ds { }; /* - * The shmid64_ds structure for i386 architecture. + * The generic shmid64_ds structure for x86 architecture. * Note extra padding because this structure is passed back and forth * between kernel and user space. * @@ -118,11 +125,17 @@ struct l_shmid64_ds { struct l_ipc64_perm shm_perm; /* operation perms */ l_size_t shm_segsz; /* size of segment (bytes) */ l_time_t shm_atime; /* last attach time */ +#if !defined(__LP64__) || defined(COMPAT_LINUX32) l_ulong __unused1; +#endif l_time_t shm_dtime; /* last detach time */ +#if !defined(__LP64__) || defined(COMPAT_LINUX32) l_ulong __unused2; +#endif l_time_t shm_ctime; /* last change time */ +#if !defined(__LP64__) || defined(COMPAT_LINUX32) l_ulong __unused3; +#endif l_pid_t shm_cpid; /* pid of creator */ l_pid_t shm_lpid; /* pid of last operator */ l_ulong shm_nattch; /* no. of current attaches */ @@ -131,15 +144,15 @@ struct l_shmid64_ds { }; struct l_shminfo64 { - l_ulong shmmax; - l_ulong shmmin; - l_ulong shmmni; - l_ulong shmseg; - l_ulong shmall; + l_ulong shmmax; + l_ulong shmmin; + l_ulong shmmni; + l_ulong shmseg; + l_ulong shmall; l_ulong __unused1; - l_ulong __unused2; - l_ulong __unused3; - l_ulong __unused4; + l_ulong __unused2; + l_ulong __unused3; + l_ulong __unused4; }; -#endif /* !_I386_LINUX_LINUX_IPC64_H_ */ +#endif /* !LINUX_IPC64_H_ */ Modified: head/sys/i386/linux/linux.h ============================================================================== --- head/sys/i386/linux/linux.h Tue Mar 7 16:09:37 2017 (r314865) +++ head/sys/i386/linux/linux.h Tue Mar 7 17:07:16 2017 (r314866) @@ -453,16 +453,6 @@ union l_semun { void *__pad; }; -struct l_ipc_perm { - l_key_t key; - l_uid16_t uid; - l_gid16_t gid; - l_uid16_t cuid; - l_gid16_t cgid; - l_ushort mode; - l_ushort seq; -}; - /* * Socket defines */