From nobody Sat Jul 22 11:09:19 2023 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4R7Nwb6tdHz4nx05; Sat, 22 Jul 2023 11:09:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4R7Nwb3FRqz3svP; Sat, 22 Jul 2023 11:09:19 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1690024159; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=56keMqqRkZgWNNeYBDTzcX9Aj25OhXtYcjiW7l6UyCY=; b=LtaC1XxMvNolJxTGWhCAwR4k1wMAA7aIXcdq2HzkXdbvFygIAV68gm6Q0157q5S8bFc+7x hHL0VSx0sfM3pMuqhBgj7DPRxxOXRagEi6NxU+VZj3uU7BvhNxJXYw3owPdZG9+XusQrHy LiLJ/Yti5QAAtWSoefAKybmCFbt1WKhrKDYlcJoFrDSxioZpKs3zgpRqz0W1E8+PiA47Tb ioIaxIBraZ7Tm1pD63D44Qr0ZeIk4FEs1UvG17/yUZc2z/DhO1ij7QcGWxFzxPL+BsXBdc VeYY995dywXwZk+MVR9FfmlDyDjWN6vNLk4n+djyxaTG/E8nkPoKXpwgqDznog== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1690024159; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=56keMqqRkZgWNNeYBDTzcX9Aj25OhXtYcjiW7l6UyCY=; b=O2JKWJK05pOXG13elcTa0CjUEhoYA7MvxaNSy2BN2WUyqoc+wPrQ39ET1tgfbKbp+35WFo v16hrfZ4ROaW8F7exFBWL5xNEah0hPObAP89f8owmvV6HChG2vhpYySri3C3K5MeKPdSiO cuR9FyHILHo2BQH23GO8mvpoeZooPTITJnnECpehaUb8lDIKZQmn4GkCvNC9PpamMRzHAa IENPIsnVGi6IogQHb15Jl+XeXhg/65U1UwSn8kLhqEKz5eJtxfksRJj+LUYbjP0lrmMLUr +W44u4Jdw50VBCmCFIT6RTbV8+8IVMhAEElBc90qUuFFuQ6GJphZhA4trtyBjA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1690024159; a=rsa-sha256; cv=none; b=Dl1nBOmEXnElw5zjygvQSUecTVcrBwEPjZm0M4ImSzfGFjhqCm/mql8DEK/BxDb8JCJhj7 KAtI19Iqdr+fFLqZJhy8c4PhtitpyiZm0WDk0Pk0pEC4p5IL64KNPug0emw2H6AXvd96BI J/hq3qAqZFqrcFqTY9utdl65MuIZpyci8Sk4M2wbxWTI59/YBaI4H6waBQYZ/kQGKyMzvP IHkGNtsFP3yK0RBYYsAOZ2Bhf7CkNf+7k8n7cer5NhbuqYIfMtimxAPxMoTTAloWRsReVI VzDotLP6JABW7lo97cnYhG0UGUoQObg3d8Yh04q0BwJNoEnz5VJ1XME0vpzHPw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4R7Nwb1Rr7zsZF; Sat, 22 Jul 2023 11:09:19 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 36MB9JoY049734; Sat, 22 Jul 2023 11:09:19 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 36MB9JVN049733; Sat, 22 Jul 2023 11:09:19 GMT (envelope-from git) Date: Sat, 22 Jul 2023 11:09:19 GMT Message-Id: <202307221109.36MB9JVN049733@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Dmitry Chagin Subject: git: 22dca7acf775 - main - linux(4): Implement xattr syscalls List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: dchagin X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 22dca7acf7756c07d3ccbfdc8dfd10fd9ad3f9cf Auto-Submitted: auto-generated The branch main has been updated by dchagin: URL: https://cgit.FreeBSD.org/src/commit/?id=22dca7acf7756c07d3ccbfdc8dfd10fd9ad3f9cf commit 22dca7acf7756c07d3ccbfdc8dfd10fd9ad3f9cf Author: Dmitry Chagin AuthorDate: 2023-07-22 11:03:33 +0000 Commit: Dmitry Chagin CommitDate: 2023-07-22 11:03:33 +0000 linux(4): Implement xattr syscalls Reviewed by: Differential revision: https://reviews.freebsd.org/D35544 MFC after: 1 month --- sys/compat/linux/linux_dummy.c | 21 --- sys/compat/linux/linux_xattr.c | 399 +++++++++++++++++++++++++++++++++++++++++ sys/modules/linux/Makefile | 1 + sys/modules/linux64/Makefile | 1 + 4 files changed, 401 insertions(+), 21 deletions(-) diff --git a/sys/compat/linux/linux_dummy.c b/sys/compat/linux/linux_dummy.c index 46596aa4a92a..861482b67d8f 100644 --- a/sys/compat/linux/linux_dummy.c +++ b/sys/compat/linux/linux_dummy.c @@ -146,24 +146,3 @@ DUMMY(pidfd_send_signal); DUMMY(io_uring_setup); DUMMY(io_uring_enter); DUMMY(io_uring_register); - -#define DUMMY_XATTR(s) \ -int \ -linux_ ## s ## xattr( \ - struct thread *td, struct linux_ ## s ## xattr_args *arg) \ -{ \ - \ - return (EOPNOTSUPP); \ -} -DUMMY_XATTR(set); -DUMMY_XATTR(lset); -DUMMY_XATTR(fset); -DUMMY_XATTR(get); -DUMMY_XATTR(lget); -DUMMY_XATTR(fget); -DUMMY_XATTR(list); -DUMMY_XATTR(llist); -DUMMY_XATTR(flist); -DUMMY_XATTR(remove); -DUMMY_XATTR(lremove); -DUMMY_XATTR(fremove); diff --git a/sys/compat/linux/linux_xattr.c b/sys/compat/linux/linux_xattr.c new file mode 100644 index 000000000000..60c4c8ddf4c9 --- /dev/null +++ b/sys/compat/linux/linux_xattr.c @@ -0,0 +1,399 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Dmitry Chagin + * + * Redistribution and use in source and binary forms, with or without + * 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. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#ifdef COMPAT_LINUX32 +#include +#include +#else +#include +#include +#endif + +#include + +#define LINUX_XATTR_SIZE_MAX 65536 +#define LINUX_XATTR_LIST_MAX 65536 +#define LINUX_XATTR_NAME_MAX 255 + +#define LINUX_XATTR_CREATE 0x1 +#define LINUX_XATTR_REPLACE 0x2 +#define LINUX_XATTR_FLAGS LINUX_XATTR_CREATE|LINUX_XATTR_REPLACE + +struct listxattr_args { + int fd; + const char *path; + char *list; + l_size_t size; + int follow; +}; + +struct setxattr_args { + int fd; + const char *path; + const char *name; + void *value; + l_size_t size; + l_int flags; + int follow; +}; + +static char *extattr_namespace_names[] = EXTATTR_NAMESPACE_NAMES; + + +static int +xatrr_to_extattr(const char *uattrname, int *attrnamespace, char *attrname) +{ + char uname[LINUX_XATTR_NAME_MAX + 1], *dot; + size_t len, cplen; + int error; + + error = copyinstr(uattrname, uname, sizeof(uname), &cplen); + if (error != 0) + return (error); + if (cplen == sizeof(uname)) + return (ERANGE); + dot = strchr(uname, '.'); + if (dot == NULL) + return (ENOTSUP); + *dot = '\0'; + for (*attrnamespace = EXTATTR_NAMESPACE_USER; + *attrnamespace < nitems(extattr_namespace_names); + (*attrnamespace)++) { + if (bcmp(uname, extattr_namespace_names[*attrnamespace], + dot - uname + 1) == 0) { + dot++; + len = strlen(dot) + 1; + bcopy(dot, attrname, len); + return (0); + } + } + return (ENOTSUP); +} + +static int +listxattr(struct thread *td, struct listxattr_args *args) +{ + char attrname[LINUX_XATTR_NAME_MAX + 1]; + char *data, *prefix, *key; + struct uio auio; + struct iovec aiov; + unsigned char keylen; + size_t sz, cnt, rs, prefixlen, pairlen; + int attrnamespace, error; + + if (args->size != 0) + sz = min(LINUX_XATTR_LIST_MAX, args->size); + else + sz = LINUX_XATTR_LIST_MAX; + + data = malloc(sz, M_LINUX, M_WAITOK); + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_td = td; + cnt = 0; + for (attrnamespace = EXTATTR_NAMESPACE_USER; + attrnamespace < nitems(extattr_namespace_names); + attrnamespace++) { + aiov.iov_base = data; + aiov.iov_len = sz; + auio.uio_resid = sz; + auio.uio_offset = 0; + + if (args->path != NULL) + error = kern_extattr_list_path(td, args->path, + attrnamespace, &auio, args->follow, UIO_USERSPACE); + else + error = kern_extattr_list_fd(td, args->fd, + attrnamespace, &auio); + rs = sz - auio.uio_resid; + if (error != 0 || rs == 0) + continue; + prefix = extattr_namespace_names[attrnamespace]; + prefixlen = strlen(prefix); + key = data; + while (rs > 0) { + keylen = (unsigned char)key[0]; + pairlen = prefixlen + 1 + keylen + 1; + if (cnt + pairlen > LINUX_XATTR_LIST_MAX) { + error = E2BIG; + break; + } + if ((args->list != NULL && cnt > args->size) || + pairlen >= sizeof(attrname)) { + error = ERANGE; + break; + } + ++key; + if (args->list != NULL) { + sprintf(attrname, "%s.%.*s", prefix, keylen, key); + error = copyout(attrname, args->list, pairlen); + if (error != 0) + break; + args->list += pairlen; + } + cnt += pairlen; + key += keylen; + rs -= (keylen + 1); + } + } + if (error == 0) + td->td_retval[0] = cnt; + free(data, M_LINUX); + return (error); +} + +int +linux_listxattr(struct thread *td, struct linux_listxattr_args *args) +{ + struct listxattr_args eargs = { + .fd = -1, + .path = args->path, + .list = args->list, + .size = args->size, + .follow = FOLLOW, + }; + + return (listxattr(td, &eargs)); +} + +int +linux_llistxattr(struct thread *td, struct linux_llistxattr_args *args) +{ + struct listxattr_args eargs = { + .fd = -1, + .path = args->path, + .list = args->list, + .size = args->size, + .follow = NOFOLLOW, + }; + + return (listxattr(td, &eargs)); +} + +int +linux_flistxattr(struct thread *td, struct linux_flistxattr_args *args) +{ + struct listxattr_args eargs = { + .fd = args->fd, + .path = NULL, + .list = args->list, + .size = args->size, + .follow = 0, + }; + + return (listxattr(td, &eargs)); +} + +static int +linux_path_removexattr(struct thread *td, const char *upath, const char *uname, + int follow) +{ + char attrname[LINUX_XATTR_NAME_MAX + 1]; + int attrnamespace, error; + + error = xatrr_to_extattr(uname, &attrnamespace, attrname); + if (error != 0) + return (error); + + return (kern_extattr_delete_path(td, upath, attrnamespace, + attrname, follow, UIO_USERSPACE)); +} + +int +linux_removexattr(struct thread *td, struct linux_removexattr_args *args) +{ + + return (linux_path_removexattr(td, args->path, args->name, + FOLLOW)); +} + +int +linux_lremovexattr(struct thread *td, struct linux_lremovexattr_args *args) +{ + + return (linux_path_removexattr(td, args->path, args->name, + NOFOLLOW)); +} + +int +linux_fremovexattr(struct thread *td, struct linux_fremovexattr_args *args) +{ + char attrname[LINUX_XATTR_NAME_MAX + 1]; + int attrnamespace, error; + + error = xatrr_to_extattr(args->name, &attrnamespace, attrname); + if (error != 0) + return (error); + return (kern_extattr_delete_fd(td, args->fd, attrnamespace, + attrname)); +} + +static int +linux_path_getxattr(struct thread *td, const char *upath, const char *uname, + void *value, l_size_t size, int follow) +{ + char attrname[LINUX_XATTR_NAME_MAX + 1]; + int attrnamespace, error; + + error = xatrr_to_extattr(uname, &attrnamespace, attrname); + if (error != 0) + return (error); + + return (kern_extattr_get_path(td, upath, attrnamespace, + attrname, value, size, follow, UIO_USERSPACE)); +} + +int +linux_getxattr(struct thread *td, struct linux_getxattr_args *args) +{ + + return (linux_path_getxattr(td, args->path, args->name, + args->value, args->size, FOLLOW)); +} + +int +linux_lgetxattr(struct thread *td, struct linux_lgetxattr_args *args) +{ + + return (linux_path_getxattr(td, args->path, args->name, + args->value, args->size, NOFOLLOW)); +} + +int +linux_fgetxattr(struct thread *td, struct linux_fgetxattr_args *args) +{ + char attrname[LINUX_XATTR_NAME_MAX + 1]; + int attrnamespace, error; + + error = xatrr_to_extattr(args->name, &attrnamespace, attrname); + if (error != 0) + return (error); + return (kern_extattr_get_fd(td, args->fd, attrnamespace, + attrname, args->value, args->size)); +} + +static int +setxattr(struct thread *td, struct setxattr_args *args) +{ + char attrname[LINUX_XATTR_NAME_MAX + 1]; + int attrnamespace, error; + + if ((args->flags & ~(LINUX_XATTR_FLAGS)) != 0 || + args->flags == (LINUX_XATTR_FLAGS)) + return (EINVAL); + error = xatrr_to_extattr(args->name, &attrnamespace, attrname); + if (error != 0) + return (error); + + if ((args->flags & (LINUX_XATTR_FLAGS)) != 0 ) { + if (args->path != NULL) + error = kern_extattr_get_path(td, args->path, + attrnamespace, attrname, NULL, args->size, + args->follow, UIO_USERSPACE); + else + error = kern_extattr_get_fd(td, args->fd, + attrnamespace, attrname, NULL, args->size); + if ((args->flags & LINUX_XATTR_CREATE) != 0) { + if (error == 0) + error = EEXIST; + else if (error == ENOATTR) + error = 0; + } + if (error != 0) + goto out; + } + if (args->path != NULL) + error = kern_extattr_set_path(td, args->path, attrnamespace, + attrname, args->value, args->size, args->follow, + UIO_USERSPACE); + else + error = kern_extattr_set_fd(td, args->fd, attrnamespace, + attrname, args->value, args->size); +out: + td->td_retval[0] = 0; + return (error); +} + +int +linux_setxattr(struct thread *td, struct linux_setxattr_args *args) +{ + struct setxattr_args eargs = { + .fd = -1, + .path = args->path, + .name = args->name, + .value = args->value, + .size = args->size, + .flags = args->flags, + .follow = FOLLOW, + }; + + return (setxattr(td, &eargs)); +} + +int +linux_lsetxattr(struct thread *td, struct linux_lsetxattr_args *args) +{ + struct setxattr_args eargs = { + .fd = -1, + .path = args->path, + .name = args->name, + .value = args->value, + .size = args->size, + .flags = args->flags, + .follow = NOFOLLOW, + }; + + return (setxattr(td, &eargs)); +} + +int +linux_fsetxattr(struct thread *td, struct linux_fsetxattr_args *args) +{ + struct setxattr_args eargs = { + .fd = args->fd, + .path = NULL, + .name = args->name, + .value = args->value, + .size = args->size, + .flags = args->flags, + .follow = 0, + }; + + return (setxattr(td, &eargs)); +} diff --git a/sys/modules/linux/Makefile b/sys/modules/linux/Makefile index 294a7d595cc6..42ce6607dfc2 100644 --- a/sys/modules/linux/Makefile +++ b/sys/modules/linux/Makefile @@ -34,6 +34,7 @@ SRCS= linux${SFX}_dummy_machdep.c \ linux_timer.c \ linux_uid16.c \ linux_vdso.c \ + linux_xattr.c \ opt_inet6.h \ opt_ktrace.h \ opt_posix.h \ diff --git a/sys/modules/linux64/Makefile b/sys/modules/linux64/Makefile index 4fe9ccd576c1..0a133e6e79b4 100644 --- a/sys/modules/linux64/Makefile +++ b/sys/modules/linux64/Makefile @@ -29,6 +29,7 @@ SRCS= linux_dummy_machdep.c \ linux_time.c \ linux_vdso.c \ linux_timer.c \ + linux_xattr.c \ opt_ktrace.h \ opt_inet6.h \ opt_posix.h \