1cdd6ea94SMariusz Zaborski /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3cdd6ea94SMariusz Zaborski *
4dcdad299SMariusz Zaborski * Copyright (c) 2018-2021 Mariusz Zaborski <oshogbo@FreeBSD.org>
5cdd6ea94SMariusz Zaborski * All rights reserved.
6cdd6ea94SMariusz Zaborski *
7cdd6ea94SMariusz Zaborski * Redistribution and use in source and binary forms, with or without
8cdd6ea94SMariusz Zaborski * modification, are permitted provided that the following conditions
9cdd6ea94SMariusz Zaborski * are met:
10cdd6ea94SMariusz Zaborski * 1. Redistributions of source code must retain the above copyright
11cdd6ea94SMariusz Zaborski * notice, this list of conditions and the following disclaimer.
12cdd6ea94SMariusz Zaborski * 2. Redistributions in binary form must reproduce the above copyright
13cdd6ea94SMariusz Zaborski * notice, this list of conditions and the following disclaimer in the
14cdd6ea94SMariusz Zaborski * documentation and/or other materials provided with the distribution.
15cdd6ea94SMariusz Zaborski *
16cdd6ea94SMariusz Zaborski * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17cdd6ea94SMariusz Zaborski * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18cdd6ea94SMariusz Zaborski * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19cdd6ea94SMariusz Zaborski * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20cdd6ea94SMariusz Zaborski * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21cdd6ea94SMariusz Zaborski * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22cdd6ea94SMariusz Zaborski * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23cdd6ea94SMariusz Zaborski * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24cdd6ea94SMariusz Zaborski * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25cdd6ea94SMariusz Zaborski * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26cdd6ea94SMariusz Zaborski * SUCH DAMAGE.
27cdd6ea94SMariusz Zaborski */
28cdd6ea94SMariusz Zaborski
29cdd6ea94SMariusz Zaborski #include <sys/types.h>
30cdd6ea94SMariusz Zaborski #include <sys/capsicum.h>
31cdd6ea94SMariusz Zaborski #include <sys/sysctl.h>
32cdd6ea94SMariusz Zaborski #include <sys/cnv.h>
33cdd6ea94SMariusz Zaborski #include <sys/dnv.h>
34cdd6ea94SMariusz Zaborski #include <sys/nv.h>
357b558caeSEd Maste #include <sys/stat.h>
36cdd6ea94SMariusz Zaborski
37cdd6ea94SMariusz Zaborski #include <assert.h>
38cdd6ea94SMariusz Zaborski #include <errno.h>
39cdd6ea94SMariusz Zaborski #include <stdlib.h>
40cdd6ea94SMariusz Zaborski #include <string.h>
41cdd6ea94SMariusz Zaborski #include <unistd.h>
42cdd6ea94SMariusz Zaborski
43cdd6ea94SMariusz Zaborski #include <libcasper.h>
44cdd6ea94SMariusz Zaborski #include <libcasper_service.h>
45cdd6ea94SMariusz Zaborski
46cdd6ea94SMariusz Zaborski #include "cap_fileargs.h"
47cdd6ea94SMariusz Zaborski
48cdd6ea94SMariusz Zaborski #define CACHE_SIZE 128
49cdd6ea94SMariusz Zaborski
50cdd6ea94SMariusz Zaborski #define FILEARGS_MAGIC 0xFA00FA00
51cdd6ea94SMariusz Zaborski
52cdd6ea94SMariusz Zaborski struct fileargs {
53cdd6ea94SMariusz Zaborski uint32_t fa_magic;
54cdd6ea94SMariusz Zaborski nvlist_t *fa_cache;
55cdd6ea94SMariusz Zaborski cap_channel_t *fa_chann;
56cdd6ea94SMariusz Zaborski int fa_fdflags;
57cdd6ea94SMariusz Zaborski };
58cdd6ea94SMariusz Zaborski
59cdd6ea94SMariusz Zaborski static int
fileargs_get_lstat_cache(fileargs_t * fa,const char * name,struct stat * sb)607b558caeSEd Maste fileargs_get_lstat_cache(fileargs_t *fa, const char *name, struct stat *sb)
617b558caeSEd Maste {
627b558caeSEd Maste const nvlist_t *nvl;
637b558caeSEd Maste size_t size;
647b558caeSEd Maste const void *buf;
657b558caeSEd Maste
667b558caeSEd Maste assert(fa != NULL);
677b558caeSEd Maste assert(fa->fa_magic == FILEARGS_MAGIC);
687b558caeSEd Maste assert(name != NULL);
697b558caeSEd Maste
707b558caeSEd Maste if (fa->fa_cache == NULL)
717b558caeSEd Maste return (-1);
727b558caeSEd Maste
737b558caeSEd Maste nvl = dnvlist_get_nvlist(fa->fa_cache, name, NULL);
747b558caeSEd Maste if (nvl == NULL)
757b558caeSEd Maste return (-1);
767b558caeSEd Maste
777b558caeSEd Maste if (!nvlist_exists_binary(nvl, "stat")) {
787b558caeSEd Maste return (-1);
797b558caeSEd Maste }
807b558caeSEd Maste
817b558caeSEd Maste buf = nvlist_get_binary(nvl, "stat", &size);
827b558caeSEd Maste assert(size == sizeof(*sb));
837b558caeSEd Maste memcpy(sb, buf, size);
847b558caeSEd Maste
857b558caeSEd Maste return (0);
867b558caeSEd Maste }
877b558caeSEd Maste
887b558caeSEd Maste static int
fileargs_get_fd_cache(fileargs_t * fa,const char * name)897b558caeSEd Maste fileargs_get_fd_cache(fileargs_t *fa, const char *name)
90cdd6ea94SMariusz Zaborski {
91cdd6ea94SMariusz Zaborski int fd;
92cdd6ea94SMariusz Zaborski const nvlist_t *nvl;
93cdd6ea94SMariusz Zaborski nvlist_t *tnvl;
94cdd6ea94SMariusz Zaborski
95cdd6ea94SMariusz Zaborski assert(fa != NULL);
96cdd6ea94SMariusz Zaborski assert(fa->fa_magic == FILEARGS_MAGIC);
97cdd6ea94SMariusz Zaborski assert(name != NULL);
98cdd6ea94SMariusz Zaborski
99cdd6ea94SMariusz Zaborski if (fa->fa_cache == NULL)
100cdd6ea94SMariusz Zaborski return (-1);
101cdd6ea94SMariusz Zaborski
102cdd6ea94SMariusz Zaborski if ((fa->fa_fdflags & O_CREAT) != 0)
103cdd6ea94SMariusz Zaborski return (-1);
104cdd6ea94SMariusz Zaborski
105cdd6ea94SMariusz Zaborski nvl = dnvlist_get_nvlist(fa->fa_cache, name, NULL);
106cdd6ea94SMariusz Zaborski if (nvl == NULL)
107cdd6ea94SMariusz Zaborski return (-1);
108cdd6ea94SMariusz Zaborski
109cdd6ea94SMariusz Zaborski tnvl = nvlist_take_nvlist(fa->fa_cache, name);
1107b558caeSEd Maste
1117b558caeSEd Maste if (!nvlist_exists_descriptor(tnvl, "fd")) {
1127b558caeSEd Maste nvlist_destroy(tnvl);
1137b558caeSEd Maste return (-1);
1147b558caeSEd Maste }
1157b558caeSEd Maste
116cdd6ea94SMariusz Zaborski fd = nvlist_take_descriptor(tnvl, "fd");
117cdd6ea94SMariusz Zaborski nvlist_destroy(tnvl);
118cdd6ea94SMariusz Zaborski
119cdd6ea94SMariusz Zaborski if ((fa->fa_fdflags & O_CLOEXEC) != O_CLOEXEC) {
120cdd6ea94SMariusz Zaborski if (fcntl(fd, F_SETFD, fa->fa_fdflags) == -1) {
121cdd6ea94SMariusz Zaborski close(fd);
122cdd6ea94SMariusz Zaborski return (-1);
123cdd6ea94SMariusz Zaborski }
124cdd6ea94SMariusz Zaborski }
125cdd6ea94SMariusz Zaborski
126cdd6ea94SMariusz Zaborski return (fd);
127cdd6ea94SMariusz Zaborski }
128cdd6ea94SMariusz Zaborski
129cdd6ea94SMariusz Zaborski static void
fileargs_set_cache(fileargs_t * fa,nvlist_t * nvl)130cdd6ea94SMariusz Zaborski fileargs_set_cache(fileargs_t *fa, nvlist_t *nvl)
131cdd6ea94SMariusz Zaborski {
132cdd6ea94SMariusz Zaborski
133cdd6ea94SMariusz Zaborski nvlist_destroy(fa->fa_cache);
134cdd6ea94SMariusz Zaborski fa->fa_cache = nvl;
135cdd6ea94SMariusz Zaborski }
136cdd6ea94SMariusz Zaborski
137cdd6ea94SMariusz Zaborski static nvlist_t*
fileargs_fetch(fileargs_t * fa,const char * name,const char * cmd)1387b558caeSEd Maste fileargs_fetch(fileargs_t *fa, const char *name, const char *cmd)
139cdd6ea94SMariusz Zaborski {
140cdd6ea94SMariusz Zaborski nvlist_t *nvl;
141cdd6ea94SMariusz Zaborski int serrno;
142cdd6ea94SMariusz Zaborski
143cdd6ea94SMariusz Zaborski assert(fa != NULL);
144cdd6ea94SMariusz Zaborski assert(name != NULL);
145cdd6ea94SMariusz Zaborski
146cdd6ea94SMariusz Zaborski nvl = nvlist_create(NV_FLAG_NO_UNIQUE);
1477b558caeSEd Maste nvlist_add_string(nvl, "cmd", cmd);
148cdd6ea94SMariusz Zaborski nvlist_add_string(nvl, "name", name);
149cdd6ea94SMariusz Zaborski
150cdd6ea94SMariusz Zaborski nvl = cap_xfer_nvlist(fa->fa_chann, nvl);
151cdd6ea94SMariusz Zaborski if (nvl == NULL)
152cdd6ea94SMariusz Zaborski return (NULL);
153cdd6ea94SMariusz Zaborski
154cdd6ea94SMariusz Zaborski if (nvlist_get_number(nvl, "error") != 0) {
155cdd6ea94SMariusz Zaborski serrno = (int)nvlist_get_number(nvl, "error");
156cdd6ea94SMariusz Zaborski nvlist_destroy(nvl);
157cdd6ea94SMariusz Zaborski errno = serrno;
158cdd6ea94SMariusz Zaborski return (NULL);
159cdd6ea94SMariusz Zaborski }
160cdd6ea94SMariusz Zaborski
161cdd6ea94SMariusz Zaborski return (nvl);
162cdd6ea94SMariusz Zaborski }
163cdd6ea94SMariusz Zaborski
164cdd6ea94SMariusz Zaborski static nvlist_t *
fileargs_create_limit(int argc,const char * const * argv,int flags,mode_t mode,cap_rights_t * rightsp,int operations)165cdd6ea94SMariusz Zaborski fileargs_create_limit(int argc, const char * const *argv, int flags,
1667b558caeSEd Maste mode_t mode, cap_rights_t *rightsp, int operations)
167cdd6ea94SMariusz Zaborski {
168cdd6ea94SMariusz Zaborski nvlist_t *limits;
169cdd6ea94SMariusz Zaborski int i;
170cdd6ea94SMariusz Zaborski
171cdd6ea94SMariusz Zaborski limits = nvlist_create(NV_FLAG_NO_UNIQUE);
172cdd6ea94SMariusz Zaborski if (limits == NULL)
173cdd6ea94SMariusz Zaborski return (NULL);
174cdd6ea94SMariusz Zaborski
175cdd6ea94SMariusz Zaborski nvlist_add_number(limits, "flags", flags);
1767b558caeSEd Maste nvlist_add_number(limits, "operations", operations);
177cdd6ea94SMariusz Zaborski if (rightsp != NULL) {
178cdd6ea94SMariusz Zaborski nvlist_add_binary(limits, "cap_rights", rightsp,
179cdd6ea94SMariusz Zaborski sizeof(*rightsp));
180cdd6ea94SMariusz Zaborski }
181cdd6ea94SMariusz Zaborski if ((flags & O_CREAT) != 0)
182cdd6ea94SMariusz Zaborski nvlist_add_number(limits, "mode", (uint64_t)mode);
183cdd6ea94SMariusz Zaborski
184cdd6ea94SMariusz Zaborski for (i = 0; i < argc; i++) {
18595097753SMariusz Zaborski if (strlen(argv[i]) >= MAXPATHLEN) {
18695097753SMariusz Zaborski nvlist_destroy(limits);
18795097753SMariusz Zaborski errno = ENAMETOOLONG;
18895097753SMariusz Zaborski return (NULL);
18995097753SMariusz Zaborski }
190cdd6ea94SMariusz Zaborski nvlist_add_null(limits, argv[i]);
191cdd6ea94SMariusz Zaborski }
192cdd6ea94SMariusz Zaborski
193cdd6ea94SMariusz Zaborski return (limits);
194cdd6ea94SMariusz Zaborski }
195cdd6ea94SMariusz Zaborski
196cdd6ea94SMariusz Zaborski static fileargs_t *
fileargs_create(cap_channel_t * chan,int fdflags)197cdd6ea94SMariusz Zaborski fileargs_create(cap_channel_t *chan, int fdflags)
198cdd6ea94SMariusz Zaborski {
199cdd6ea94SMariusz Zaborski fileargs_t *fa;
200cdd6ea94SMariusz Zaborski
201cdd6ea94SMariusz Zaborski fa = malloc(sizeof(*fa));
202cdd6ea94SMariusz Zaborski if (fa != NULL) {
203cdd6ea94SMariusz Zaborski fa->fa_cache = NULL;
204cdd6ea94SMariusz Zaborski fa->fa_chann = chan;
205cdd6ea94SMariusz Zaborski fa->fa_fdflags = fdflags;
206cdd6ea94SMariusz Zaborski fa->fa_magic = FILEARGS_MAGIC;
207cdd6ea94SMariusz Zaborski }
208cdd6ea94SMariusz Zaborski
209cdd6ea94SMariusz Zaborski return (fa);
210cdd6ea94SMariusz Zaborski }
211cdd6ea94SMariusz Zaborski
212cdd6ea94SMariusz Zaborski fileargs_t *
fileargs_init(int argc,char * argv[],int flags,mode_t mode,cap_rights_t * rightsp,int operations)213cdd6ea94SMariusz Zaborski fileargs_init(int argc, char *argv[], int flags, mode_t mode,
2147b558caeSEd Maste cap_rights_t *rightsp, int operations)
215cdd6ea94SMariusz Zaborski {
216cdd6ea94SMariusz Zaborski nvlist_t *limits;
217cdd6ea94SMariusz Zaborski
2182607c01bSMariusz Zaborski if (argc <= 0 || argv == NULL) {
219cdd6ea94SMariusz Zaborski return (fileargs_create(NULL, 0));
220cdd6ea94SMariusz Zaborski }
221cdd6ea94SMariusz Zaborski
222cdd6ea94SMariusz Zaborski limits = fileargs_create_limit(argc, (const char * const *)argv, flags,
2237b558caeSEd Maste mode, rightsp, operations);
224cdd6ea94SMariusz Zaborski if (limits == NULL)
225cdd6ea94SMariusz Zaborski return (NULL);
226cdd6ea94SMariusz Zaborski
227cdd6ea94SMariusz Zaborski return (fileargs_initnv(limits));
228cdd6ea94SMariusz Zaborski }
229cdd6ea94SMariusz Zaborski
230cdd6ea94SMariusz Zaborski fileargs_t *
fileargs_cinit(cap_channel_t * cas,int argc,char * argv[],int flags,mode_t mode,cap_rights_t * rightsp,int operations)231cdd6ea94SMariusz Zaborski fileargs_cinit(cap_channel_t *cas, int argc, char *argv[], int flags,
2327b558caeSEd Maste mode_t mode, cap_rights_t *rightsp, int operations)
233cdd6ea94SMariusz Zaborski {
234cdd6ea94SMariusz Zaborski nvlist_t *limits;
235cdd6ea94SMariusz Zaborski
2362607c01bSMariusz Zaborski if (argc <= 0 || argv == NULL) {
237cdd6ea94SMariusz Zaborski return (fileargs_create(NULL, 0));
238cdd6ea94SMariusz Zaborski }
239cdd6ea94SMariusz Zaborski
240cdd6ea94SMariusz Zaborski limits = fileargs_create_limit(argc, (const char * const *)argv, flags,
2417b558caeSEd Maste mode, rightsp, operations);
242cdd6ea94SMariusz Zaborski if (limits == NULL)
243cdd6ea94SMariusz Zaborski return (NULL);
244cdd6ea94SMariusz Zaborski
245cdd6ea94SMariusz Zaborski return (fileargs_cinitnv(cas, limits));
246cdd6ea94SMariusz Zaborski }
247cdd6ea94SMariusz Zaborski
248cdd6ea94SMariusz Zaborski fileargs_t *
fileargs_initnv(nvlist_t * limits)249cdd6ea94SMariusz Zaborski fileargs_initnv(nvlist_t *limits)
250cdd6ea94SMariusz Zaborski {
251cdd6ea94SMariusz Zaborski cap_channel_t *cas;
252cdd6ea94SMariusz Zaborski fileargs_t *fa;
253cdd6ea94SMariusz Zaborski
254cdd6ea94SMariusz Zaborski if (limits == NULL) {
255cdd6ea94SMariusz Zaborski return (fileargs_create(NULL, 0));
256cdd6ea94SMariusz Zaborski }
257cdd6ea94SMariusz Zaborski
258cdd6ea94SMariusz Zaborski cas = cap_init();
259cdd6ea94SMariusz Zaborski if (cas == NULL) {
260cdd6ea94SMariusz Zaborski nvlist_destroy(limits);
261cdd6ea94SMariusz Zaborski return (NULL);
262cdd6ea94SMariusz Zaborski }
263cdd6ea94SMariusz Zaborski
264cdd6ea94SMariusz Zaborski fa = fileargs_cinitnv(cas, limits);
265cdd6ea94SMariusz Zaborski cap_close(cas);
266cdd6ea94SMariusz Zaborski
267cdd6ea94SMariusz Zaborski return (fa);
268cdd6ea94SMariusz Zaborski }
269cdd6ea94SMariusz Zaborski
270cdd6ea94SMariusz Zaborski fileargs_t *
fileargs_cinitnv(cap_channel_t * cas,nvlist_t * limits)271cdd6ea94SMariusz Zaborski fileargs_cinitnv(cap_channel_t *cas, nvlist_t *limits)
272cdd6ea94SMariusz Zaborski {
273cdd6ea94SMariusz Zaborski cap_channel_t *chann;
274cdd6ea94SMariusz Zaborski fileargs_t *fa;
2751e9ce60aSMariusz Zaborski int flags, ret, serrno;
276cdd6ea94SMariusz Zaborski
277cdd6ea94SMariusz Zaborski assert(cas != NULL);
278cdd6ea94SMariusz Zaborski
279cdd6ea94SMariusz Zaborski if (limits == NULL) {
280cdd6ea94SMariusz Zaborski return (fileargs_create(NULL, 0));
281cdd6ea94SMariusz Zaborski }
282cdd6ea94SMariusz Zaborski
283cdd6ea94SMariusz Zaborski chann = NULL;
284cdd6ea94SMariusz Zaborski fa = NULL;
285cdd6ea94SMariusz Zaborski
286cdd6ea94SMariusz Zaborski chann = cap_service_open(cas, "system.fileargs");
287cdd6ea94SMariusz Zaborski if (chann == NULL) {
288cdd6ea94SMariusz Zaborski nvlist_destroy(limits);
289cdd6ea94SMariusz Zaborski return (NULL);
290cdd6ea94SMariusz Zaborski }
291cdd6ea94SMariusz Zaborski
292cdd6ea94SMariusz Zaborski flags = nvlist_get_number(limits, "flags");
2931e9ce60aSMariusz Zaborski (void)nvlist_get_number(limits, "operations");
294cdd6ea94SMariusz Zaborski
295cdd6ea94SMariusz Zaborski /* Limits are consumed no need to free them. */
296cdd6ea94SMariusz Zaborski ret = cap_limit_set(chann, limits);
297cdd6ea94SMariusz Zaborski if (ret < 0)
298cdd6ea94SMariusz Zaborski goto out;
299cdd6ea94SMariusz Zaborski
300cdd6ea94SMariusz Zaborski fa = fileargs_create(chann, flags);
301cdd6ea94SMariusz Zaborski if (fa == NULL)
302cdd6ea94SMariusz Zaborski goto out;
303cdd6ea94SMariusz Zaborski
304cdd6ea94SMariusz Zaborski return (fa);
305cdd6ea94SMariusz Zaborski out:
306cdd6ea94SMariusz Zaborski serrno = errno;
307cdd6ea94SMariusz Zaborski if (chann != NULL)
308cdd6ea94SMariusz Zaborski cap_close(chann);
309cdd6ea94SMariusz Zaborski errno = serrno;
310cdd6ea94SMariusz Zaborski return (NULL);
311cdd6ea94SMariusz Zaborski }
312cdd6ea94SMariusz Zaborski
313cdd6ea94SMariusz Zaborski int
fileargs_open(fileargs_t * fa,const char * name)314cdd6ea94SMariusz Zaborski fileargs_open(fileargs_t *fa, const char *name)
315cdd6ea94SMariusz Zaborski {
316cdd6ea94SMariusz Zaborski int fd;
317cdd6ea94SMariusz Zaborski nvlist_t *nvl;
318cdd6ea94SMariusz Zaborski char *cmd;
319cdd6ea94SMariusz Zaborski
320cdd6ea94SMariusz Zaborski assert(fa != NULL);
321cdd6ea94SMariusz Zaborski assert(fa->fa_magic == FILEARGS_MAGIC);
322cdd6ea94SMariusz Zaborski
323cdd6ea94SMariusz Zaborski if (name == NULL) {
324cdd6ea94SMariusz Zaborski errno = EINVAL;
325cdd6ea94SMariusz Zaborski return (-1);
326cdd6ea94SMariusz Zaborski }
327cdd6ea94SMariusz Zaborski
328cdd6ea94SMariusz Zaborski if (fa->fa_chann == NULL) {
329cdd6ea94SMariusz Zaborski errno = ENOTCAPABLE;
330cdd6ea94SMariusz Zaborski return (-1);
331cdd6ea94SMariusz Zaborski }
332cdd6ea94SMariusz Zaborski
3337b558caeSEd Maste fd = fileargs_get_fd_cache(fa, name);
334cdd6ea94SMariusz Zaborski if (fd != -1)
335cdd6ea94SMariusz Zaborski return (fd);
336cdd6ea94SMariusz Zaborski
3377b558caeSEd Maste nvl = fileargs_fetch(fa, name, "open");
338cdd6ea94SMariusz Zaborski if (nvl == NULL)
339cdd6ea94SMariusz Zaborski return (-1);
340cdd6ea94SMariusz Zaborski
341cdd6ea94SMariusz Zaborski fd = nvlist_take_descriptor(nvl, "fd");
342cdd6ea94SMariusz Zaborski cmd = nvlist_take_string(nvl, "cmd");
343cdd6ea94SMariusz Zaborski if (strcmp(cmd, "cache") == 0)
344cdd6ea94SMariusz Zaborski fileargs_set_cache(fa, nvl);
345cdd6ea94SMariusz Zaborski else
346cdd6ea94SMariusz Zaborski nvlist_destroy(nvl);
347cdd6ea94SMariusz Zaborski free(cmd);
348cdd6ea94SMariusz Zaborski
349cdd6ea94SMariusz Zaborski return (fd);
350cdd6ea94SMariusz Zaborski }
351cdd6ea94SMariusz Zaborski
352cdd6ea94SMariusz Zaborski FILE *
fileargs_fopen(fileargs_t * fa,const char * name,const char * mode)353cdd6ea94SMariusz Zaborski fileargs_fopen(fileargs_t *fa, const char *name, const char *mode)
354cdd6ea94SMariusz Zaborski {
355cdd6ea94SMariusz Zaborski int fd;
356cdd6ea94SMariusz Zaborski
357cdd6ea94SMariusz Zaborski if ((fd = fileargs_open(fa, name)) < 0) {
358cdd6ea94SMariusz Zaborski return (NULL);
359cdd6ea94SMariusz Zaborski }
360cdd6ea94SMariusz Zaborski
361cdd6ea94SMariusz Zaborski return (fdopen(fd, mode));
362cdd6ea94SMariusz Zaborski }
363cdd6ea94SMariusz Zaborski
3647b558caeSEd Maste int
fileargs_lstat(fileargs_t * fa,const char * name,struct stat * sb)3657b558caeSEd Maste fileargs_lstat(fileargs_t *fa, const char *name, struct stat *sb)
3667b558caeSEd Maste {
3677b558caeSEd Maste nvlist_t *nvl;
3687b558caeSEd Maste const void *buf;
3697b558caeSEd Maste size_t size;
3707b558caeSEd Maste char *cmd;
3717b558caeSEd Maste
3727b558caeSEd Maste assert(fa != NULL);
3737b558caeSEd Maste assert(fa->fa_magic == FILEARGS_MAGIC);
3747b558caeSEd Maste
3757b558caeSEd Maste if (name == NULL) {
3767b558caeSEd Maste errno = EINVAL;
3777b558caeSEd Maste return (-1);
3787b558caeSEd Maste }
3797b558caeSEd Maste
3807b558caeSEd Maste if (sb == NULL) {
3817b558caeSEd Maste errno = EFAULT;
3827b558caeSEd Maste return (-1);
3837b558caeSEd Maste }
3847b558caeSEd Maste
3857b558caeSEd Maste if (fa->fa_chann == NULL) {
3867b558caeSEd Maste errno = ENOTCAPABLE;
3877b558caeSEd Maste return (-1);
3887b558caeSEd Maste }
3897b558caeSEd Maste
3907b558caeSEd Maste if (fileargs_get_lstat_cache(fa, name, sb) != -1)
3917b558caeSEd Maste return (0);
3927b558caeSEd Maste
3937b558caeSEd Maste nvl = fileargs_fetch(fa, name, "lstat");
3947b558caeSEd Maste if (nvl == NULL)
3957b558caeSEd Maste return (-1);
3967b558caeSEd Maste
3977b558caeSEd Maste buf = nvlist_get_binary(nvl, "stat", &size);
3987b558caeSEd Maste assert(size == sizeof(*sb));
3997b558caeSEd Maste memcpy(sb, buf, size);
4007b558caeSEd Maste
4017b558caeSEd Maste cmd = nvlist_take_string(nvl, "cmd");
4027b558caeSEd Maste if (strcmp(cmd, "cache") == 0)
4037b558caeSEd Maste fileargs_set_cache(fa, nvl);
4047b558caeSEd Maste else
4057b558caeSEd Maste nvlist_destroy(nvl);
4067b558caeSEd Maste free(cmd);
4077b558caeSEd Maste
4087b558caeSEd Maste return (0);
4097b558caeSEd Maste }
4107b558caeSEd Maste
411dcdad299SMariusz Zaborski char *
fileargs_realpath(fileargs_t * fa,const char * pathname,char * reserved_path)412dcdad299SMariusz Zaborski fileargs_realpath(fileargs_t *fa, const char *pathname, char *reserved_path)
413dcdad299SMariusz Zaborski {
414dcdad299SMariusz Zaborski nvlist_t *nvl;
415dcdad299SMariusz Zaborski char *ret;
416dcdad299SMariusz Zaborski
417dcdad299SMariusz Zaborski assert(fa != NULL);
418dcdad299SMariusz Zaborski assert(fa->fa_magic == FILEARGS_MAGIC);
419dcdad299SMariusz Zaborski
420dcdad299SMariusz Zaborski if (pathname == NULL) {
421dcdad299SMariusz Zaborski errno = EINVAL;
422dcdad299SMariusz Zaborski return (NULL);
423dcdad299SMariusz Zaborski }
424dcdad299SMariusz Zaborski
425dcdad299SMariusz Zaborski if (fa->fa_chann == NULL) {
426dcdad299SMariusz Zaborski errno = ENOTCAPABLE;
427dcdad299SMariusz Zaborski return (NULL);
428dcdad299SMariusz Zaborski }
429dcdad299SMariusz Zaborski
430dcdad299SMariusz Zaborski nvl = fileargs_fetch(fa, pathname, "realpath");
431dcdad299SMariusz Zaborski if (nvl == NULL)
432dcdad299SMariusz Zaborski return (NULL);
433dcdad299SMariusz Zaborski
434dcdad299SMariusz Zaborski if (reserved_path != NULL) {
435dcdad299SMariusz Zaborski ret = reserved_path;
436dcdad299SMariusz Zaborski strcpy(reserved_path,
437dcdad299SMariusz Zaborski nvlist_get_string(nvl, "realpath"));
438dcdad299SMariusz Zaborski } else {
439dcdad299SMariusz Zaborski ret = nvlist_take_string(nvl, "realpath");
440dcdad299SMariusz Zaborski }
441dcdad299SMariusz Zaborski nvlist_destroy(nvl);
442dcdad299SMariusz Zaborski
443dcdad299SMariusz Zaborski return (ret);
444dcdad299SMariusz Zaborski }
445dcdad299SMariusz Zaborski
446cdd6ea94SMariusz Zaborski void
fileargs_free(fileargs_t * fa)447cdd6ea94SMariusz Zaborski fileargs_free(fileargs_t *fa)
448cdd6ea94SMariusz Zaborski {
449cdd6ea94SMariusz Zaborski
450cdd6ea94SMariusz Zaborski if (fa == NULL)
451cdd6ea94SMariusz Zaborski return;
452cdd6ea94SMariusz Zaborski
453cdd6ea94SMariusz Zaborski assert(fa->fa_magic == FILEARGS_MAGIC);
454cdd6ea94SMariusz Zaborski
455cdd6ea94SMariusz Zaborski nvlist_destroy(fa->fa_cache);
456cdd6ea94SMariusz Zaborski if (fa->fa_chann != NULL) {
457cdd6ea94SMariusz Zaborski cap_close(fa->fa_chann);
458cdd6ea94SMariusz Zaborski }
459cdd6ea94SMariusz Zaborski explicit_bzero(&fa->fa_magic, sizeof(fa->fa_magic));
460cdd6ea94SMariusz Zaborski free(fa);
461cdd6ea94SMariusz Zaborski }
462cdd6ea94SMariusz Zaborski
4634b3f7927SMariusz Zaborski cap_channel_t *
fileargs_unwrap(fileargs_t * fa,int * flags)4644b3f7927SMariusz Zaborski fileargs_unwrap(fileargs_t *fa, int *flags)
4654b3f7927SMariusz Zaborski {
4664b3f7927SMariusz Zaborski cap_channel_t *chan;
4674b3f7927SMariusz Zaborski
4684b3f7927SMariusz Zaborski if (fa == NULL)
4694b3f7927SMariusz Zaborski return (NULL);
4704b3f7927SMariusz Zaborski
4714b3f7927SMariusz Zaborski assert(fa->fa_magic == FILEARGS_MAGIC);
4724b3f7927SMariusz Zaborski
4734b3f7927SMariusz Zaborski chan = fa->fa_chann;
4744b3f7927SMariusz Zaborski if (flags != NULL) {
4754b3f7927SMariusz Zaborski *flags = fa->fa_fdflags;
4764b3f7927SMariusz Zaborski }
4774b3f7927SMariusz Zaborski
4784b3f7927SMariusz Zaborski nvlist_destroy(fa->fa_cache);
4794b3f7927SMariusz Zaborski explicit_bzero(&fa->fa_magic, sizeof(fa->fa_magic));
4804b3f7927SMariusz Zaborski free(fa);
4814b3f7927SMariusz Zaborski
4824b3f7927SMariusz Zaborski return (chan);
4834b3f7927SMariusz Zaborski }
4844b3f7927SMariusz Zaborski
4854b3f7927SMariusz Zaborski fileargs_t *
fileargs_wrap(cap_channel_t * chan,int fdflags)4864b3f7927SMariusz Zaborski fileargs_wrap(cap_channel_t *chan, int fdflags)
4874b3f7927SMariusz Zaborski {
4884b3f7927SMariusz Zaborski
4894b3f7927SMariusz Zaborski if (chan == NULL) {
4904b3f7927SMariusz Zaborski return (NULL);
4914b3f7927SMariusz Zaborski }
4924b3f7927SMariusz Zaborski
4934b3f7927SMariusz Zaborski return (fileargs_create(chan, fdflags));
4944b3f7927SMariusz Zaborski }
4954b3f7927SMariusz Zaborski
496cdd6ea94SMariusz Zaborski /*
497cdd6ea94SMariusz Zaborski * Service functions.
498cdd6ea94SMariusz Zaborski */
499cdd6ea94SMariusz Zaborski
500cdd6ea94SMariusz Zaborski static const char *lastname;
501cdd6ea94SMariusz Zaborski static void *cacheposition;
502cdd6ea94SMariusz Zaborski static bool allcached;
503cdd6ea94SMariusz Zaborski static const cap_rights_t *caprightsp;
504cdd6ea94SMariusz Zaborski static int capflags;
5057b558caeSEd Maste static int allowed_operations;
506cdd6ea94SMariusz Zaborski static mode_t capmode;
507cdd6ea94SMariusz Zaborski
508cdd6ea94SMariusz Zaborski static int
open_file(const char * name)509cdd6ea94SMariusz Zaborski open_file(const char *name)
510cdd6ea94SMariusz Zaborski {
511cdd6ea94SMariusz Zaborski int fd, serrno;
512cdd6ea94SMariusz Zaborski
513cdd6ea94SMariusz Zaborski if ((capflags & O_CREAT) == 0)
514cdd6ea94SMariusz Zaborski fd = open(name, capflags);
515cdd6ea94SMariusz Zaborski else
516cdd6ea94SMariusz Zaborski fd = open(name, capflags, capmode);
517cdd6ea94SMariusz Zaborski if (fd < 0)
518cdd6ea94SMariusz Zaborski return (-1);
519cdd6ea94SMariusz Zaborski
520cdd6ea94SMariusz Zaborski if (caprightsp != NULL) {
52177ebcc05SMariusz Zaborski if (cap_rights_limit(fd, caprightsp) < 0 && errno != ENOSYS) {
522cdd6ea94SMariusz Zaborski serrno = errno;
523cdd6ea94SMariusz Zaborski close(fd);
524cdd6ea94SMariusz Zaborski errno = serrno;
525cdd6ea94SMariusz Zaborski return (-1);
526cdd6ea94SMariusz Zaborski }
527cdd6ea94SMariusz Zaborski }
528cdd6ea94SMariusz Zaborski
529cdd6ea94SMariusz Zaborski return (fd);
530cdd6ea94SMariusz Zaborski }
531cdd6ea94SMariusz Zaborski
532cdd6ea94SMariusz Zaborski static void
fileargs_add_cache(nvlist_t * nvlout,const nvlist_t * limits,const char * current_name)533cdd6ea94SMariusz Zaborski fileargs_add_cache(nvlist_t *nvlout, const nvlist_t *limits,
534c78e42e2SMark Johnston const char *current_name)
535cdd6ea94SMariusz Zaborski {
536cdd6ea94SMariusz Zaborski int type, i, fd;
537cdd6ea94SMariusz Zaborski void *cookie;
538cdd6ea94SMariusz Zaborski nvlist_t *new;
539cdd6ea94SMariusz Zaborski const char *fname;
5407b558caeSEd Maste struct stat sb;
541cdd6ea94SMariusz Zaborski
542cdd6ea94SMariusz Zaborski if ((capflags & O_CREAT) != 0) {
543cdd6ea94SMariusz Zaborski allcached = true;
544cdd6ea94SMariusz Zaborski return;
545cdd6ea94SMariusz Zaborski }
546cdd6ea94SMariusz Zaborski
547cdd6ea94SMariusz Zaborski cookie = cacheposition;
548cdd6ea94SMariusz Zaborski for (i = 0; i < CACHE_SIZE + 1; i++) {
549cdd6ea94SMariusz Zaborski fname = nvlist_next(limits, &type, &cookie);
550cdd6ea94SMariusz Zaborski if (fname == NULL) {
551cdd6ea94SMariusz Zaborski cacheposition = NULL;
552cdd6ea94SMariusz Zaborski lastname = NULL;
553cdd6ea94SMariusz Zaborski allcached = true;
554cdd6ea94SMariusz Zaborski return;
555cdd6ea94SMariusz Zaborski }
556cdd6ea94SMariusz Zaborski /* We doing that to catch next element name. */
557cdd6ea94SMariusz Zaborski if (i == CACHE_SIZE) {
558cdd6ea94SMariusz Zaborski break;
559cdd6ea94SMariusz Zaborski }
560cdd6ea94SMariusz Zaborski
5612b1d0c00SMariusz Zaborski if (type != NV_TYPE_NULL) {
5622b1d0c00SMariusz Zaborski i--;
5632b1d0c00SMariusz Zaborski continue;
5642b1d0c00SMariusz Zaborski }
5652b1d0c00SMariusz Zaborski if (current_name != NULL &&
5662b1d0c00SMariusz Zaborski strcmp(fname, current_name) == 0) {
567c78e42e2SMark Johnston current_name = NULL;
568cdd6ea94SMariusz Zaborski i--;
569cdd6ea94SMariusz Zaborski continue;
570cdd6ea94SMariusz Zaborski }
571cdd6ea94SMariusz Zaborski
5727b558caeSEd Maste new = nvlist_create(NV_FLAG_NO_UNIQUE);
5737b558caeSEd Maste if ((allowed_operations & FA_OPEN) != 0) {
574cdd6ea94SMariusz Zaborski fd = open_file(fname);
575cdd6ea94SMariusz Zaborski if (fd < 0) {
576cdd6ea94SMariusz Zaborski i--;
5777b558caeSEd Maste nvlist_destroy(new);
578cdd6ea94SMariusz Zaborski continue;
579cdd6ea94SMariusz Zaborski }
580cdd6ea94SMariusz Zaborski nvlist_move_descriptor(new, "fd", fd);
5817b558caeSEd Maste }
5827b558caeSEd Maste if ((allowed_operations & FA_LSTAT) != 0) {
5837b558caeSEd Maste if (lstat(fname, &sb) < 0) {
5847b558caeSEd Maste i--;
5857b558caeSEd Maste nvlist_destroy(new);
5867b558caeSEd Maste continue;
5877b558caeSEd Maste }
5887b558caeSEd Maste nvlist_add_binary(new, "stat", &sb, sizeof(sb));
5897b558caeSEd Maste }
5907b558caeSEd Maste
591c78e42e2SMark Johnston nvlist_move_nvlist(nvlout, fname, new);
592cdd6ea94SMariusz Zaborski }
593cdd6ea94SMariusz Zaborski cacheposition = cookie;
594cdd6ea94SMariusz Zaborski lastname = fname;
595cdd6ea94SMariusz Zaborski }
596cdd6ea94SMariusz Zaborski
597cdd6ea94SMariusz Zaborski static bool
fileargs_allowed(const nvlist_t * limits,const nvlist_t * request,int operation)5987b558caeSEd Maste fileargs_allowed(const nvlist_t *limits, const nvlist_t *request, int operation)
599cdd6ea94SMariusz Zaborski {
600cdd6ea94SMariusz Zaborski const char *name;
601cdd6ea94SMariusz Zaborski
6027b558caeSEd Maste if ((allowed_operations & operation) == 0)
6037b558caeSEd Maste return (false);
6047b558caeSEd Maste
605cdd6ea94SMariusz Zaborski name = dnvlist_get_string(request, "name", NULL);
606cdd6ea94SMariusz Zaborski if (name == NULL)
607cdd6ea94SMariusz Zaborski return (false);
608cdd6ea94SMariusz Zaborski
609cdd6ea94SMariusz Zaborski /* Fast path. */
610cdd6ea94SMariusz Zaborski if (lastname != NULL && strcmp(name, lastname) == 0)
611cdd6ea94SMariusz Zaborski return (true);
612cdd6ea94SMariusz Zaborski
613cdd6ea94SMariusz Zaborski if (!nvlist_exists_null(limits, name))
614cdd6ea94SMariusz Zaborski return (false);
615cdd6ea94SMariusz Zaborski
616cdd6ea94SMariusz Zaborski return (true);
617cdd6ea94SMariusz Zaborski }
618cdd6ea94SMariusz Zaborski
619cdd6ea94SMariusz Zaborski static int
fileargs_limit(const nvlist_t * oldlimits,const nvlist_t * newlimits)620cdd6ea94SMariusz Zaborski fileargs_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits)
621cdd6ea94SMariusz Zaborski {
622cdd6ea94SMariusz Zaborski
623cdd6ea94SMariusz Zaborski if (oldlimits != NULL)
624cdd6ea94SMariusz Zaborski return (ENOTCAPABLE);
625cdd6ea94SMariusz Zaborski
626cdd6ea94SMariusz Zaborski capflags = (int)dnvlist_get_number(newlimits, "flags", 0);
6277b558caeSEd Maste allowed_operations = (int)dnvlist_get_number(newlimits, "operations", 0);
628cdd6ea94SMariusz Zaborski if ((capflags & O_CREAT) != 0)
629cdd6ea94SMariusz Zaborski capmode = (mode_t)nvlist_get_number(newlimits, "mode");
630cdd6ea94SMariusz Zaborski else
631cdd6ea94SMariusz Zaborski capmode = 0;
632cdd6ea94SMariusz Zaborski
633cdd6ea94SMariusz Zaborski caprightsp = dnvlist_get_binary(newlimits, "cap_rights", NULL, NULL, 0);
634cdd6ea94SMariusz Zaborski
635cdd6ea94SMariusz Zaborski return (0);
636cdd6ea94SMariusz Zaborski }
637cdd6ea94SMariusz Zaborski
638cdd6ea94SMariusz Zaborski static int
fileargs_command_lstat(const nvlist_t * limits,nvlist_t * nvlin,nvlist_t * nvlout)6397b558caeSEd Maste fileargs_command_lstat(const nvlist_t *limits, nvlist_t *nvlin,
6407b558caeSEd Maste nvlist_t *nvlout)
6417b558caeSEd Maste {
642b6539d47SEd Maste int error;
6437b558caeSEd Maste const char *name;
6447b558caeSEd Maste struct stat sb;
6457b558caeSEd Maste
6467b558caeSEd Maste if (limits == NULL)
6477b558caeSEd Maste return (ENOTCAPABLE);
6487b558caeSEd Maste
6497b558caeSEd Maste if (!fileargs_allowed(limits, nvlin, FA_LSTAT))
6507b558caeSEd Maste return (ENOTCAPABLE);
6517b558caeSEd Maste
6527b558caeSEd Maste name = nvlist_get_string(nvlin, "name");
6537b558caeSEd Maste
654b6539d47SEd Maste error = lstat(name, &sb);
655151744cfSEd Maste if (error < 0)
6567b558caeSEd Maste return (errno);
6577b558caeSEd Maste
6587b558caeSEd Maste if (!allcached && (lastname == NULL ||
6597b558caeSEd Maste strcmp(name, lastname) == 0)) {
6607b558caeSEd Maste nvlist_add_string(nvlout, "cmd", "cache");
6617b558caeSEd Maste fileargs_add_cache(nvlout, limits, name);
6627b558caeSEd Maste } else {
6637b558caeSEd Maste nvlist_add_string(nvlout, "cmd", "lstat");
6647b558caeSEd Maste }
6657b558caeSEd Maste nvlist_add_binary(nvlout, "stat", &sb, sizeof(sb));
6667b558caeSEd Maste return (0);
6677b558caeSEd Maste }
6687b558caeSEd Maste
6697b558caeSEd Maste static int
fileargs_command_realpath(const nvlist_t * limits,nvlist_t * nvlin,nvlist_t * nvlout)670dcdad299SMariusz Zaborski fileargs_command_realpath(const nvlist_t *limits, nvlist_t *nvlin,
671dcdad299SMariusz Zaborski nvlist_t *nvlout)
672dcdad299SMariusz Zaborski {
673dcdad299SMariusz Zaborski const char *pathname;
674dcdad299SMariusz Zaborski char *resolvedpath;
675dcdad299SMariusz Zaborski
676dcdad299SMariusz Zaborski if (limits == NULL)
677dcdad299SMariusz Zaborski return (ENOTCAPABLE);
678dcdad299SMariusz Zaborski
679dcdad299SMariusz Zaborski if (!fileargs_allowed(limits, nvlin, FA_REALPATH))
680dcdad299SMariusz Zaborski return (ENOTCAPABLE);
681dcdad299SMariusz Zaborski
682dcdad299SMariusz Zaborski pathname = nvlist_get_string(nvlin, "name");
683dcdad299SMariusz Zaborski resolvedpath = realpath(pathname, NULL);
684dcdad299SMariusz Zaborski if (resolvedpath == NULL)
685dcdad299SMariusz Zaborski return (errno);
686dcdad299SMariusz Zaborski
687dcdad299SMariusz Zaborski nvlist_move_string(nvlout, "realpath", resolvedpath);
688dcdad299SMariusz Zaborski return (0);
689dcdad299SMariusz Zaborski }
690dcdad299SMariusz Zaborski
691dcdad299SMariusz Zaborski static int
fileargs_command_open(const nvlist_t * limits,nvlist_t * nvlin,nvlist_t * nvlout)692cdd6ea94SMariusz Zaborski fileargs_command_open(const nvlist_t *limits, nvlist_t *nvlin,
693cdd6ea94SMariusz Zaborski nvlist_t *nvlout)
694cdd6ea94SMariusz Zaborski {
695cdd6ea94SMariusz Zaborski int fd;
696cdd6ea94SMariusz Zaborski const char *name;
697cdd6ea94SMariusz Zaborski
698cdd6ea94SMariusz Zaborski if (limits == NULL)
699cdd6ea94SMariusz Zaborski return (ENOTCAPABLE);
700cdd6ea94SMariusz Zaborski
7017b558caeSEd Maste if (!fileargs_allowed(limits, nvlin, FA_OPEN))
702cdd6ea94SMariusz Zaborski return (ENOTCAPABLE);
703cdd6ea94SMariusz Zaborski
704cdd6ea94SMariusz Zaborski name = nvlist_get_string(nvlin, "name");
705cdd6ea94SMariusz Zaborski
706cdd6ea94SMariusz Zaborski fd = open_file(name);
707cdd6ea94SMariusz Zaborski if (fd < 0)
708cdd6ea94SMariusz Zaborski return (errno);
709cdd6ea94SMariusz Zaborski
710cdd6ea94SMariusz Zaborski if (!allcached && (lastname == NULL ||
711cdd6ea94SMariusz Zaborski strcmp(name, lastname) == 0)) {
712cdd6ea94SMariusz Zaborski nvlist_add_string(nvlout, "cmd", "cache");
713cdd6ea94SMariusz Zaborski fileargs_add_cache(nvlout, limits, name);
714cdd6ea94SMariusz Zaborski } else {
715cdd6ea94SMariusz Zaborski nvlist_add_string(nvlout, "cmd", "open");
716cdd6ea94SMariusz Zaborski }
717cdd6ea94SMariusz Zaborski nvlist_move_descriptor(nvlout, "fd", fd);
718cdd6ea94SMariusz Zaborski return (0);
719cdd6ea94SMariusz Zaborski }
720cdd6ea94SMariusz Zaborski
721cdd6ea94SMariusz Zaborski static int
fileargs_command(const char * cmd,const nvlist_t * limits,nvlist_t * nvlin,nvlist_t * nvlout)722cdd6ea94SMariusz Zaborski fileargs_command(const char *cmd, const nvlist_t *limits,
723cdd6ea94SMariusz Zaborski nvlist_t *nvlin, nvlist_t *nvlout)
724cdd6ea94SMariusz Zaborski {
725cdd6ea94SMariusz Zaborski
726cdd6ea94SMariusz Zaborski if (strcmp(cmd, "open") == 0)
727cdd6ea94SMariusz Zaborski return (fileargs_command_open(limits, nvlin, nvlout));
7287b558caeSEd Maste if (strcmp(cmd, "lstat") == 0)
7297b558caeSEd Maste return (fileargs_command_lstat(limits, nvlin, nvlout));
730dcdad299SMariusz Zaborski if (strcmp(cmd, "realpath") == 0)
731dcdad299SMariusz Zaborski return (fileargs_command_realpath(limits, nvlin, nvlout));
7327b558caeSEd Maste
733cdd6ea94SMariusz Zaborski return (EINVAL);
734cdd6ea94SMariusz Zaborski }
735cdd6ea94SMariusz Zaborski
736cdd6ea94SMariusz Zaborski CREATE_SERVICE("system.fileargs", fileargs_limit, fileargs_command,
737cdd6ea94SMariusz Zaborski CASPER_SERVICE_FD | CASPER_SERVICE_STDIO | CASPER_SERVICE_NO_UNIQ_LIMITS);
738