svn commit: r346315 - head/lib/libcasper/services/cap_fileargs
Ed Maste
emaste at FreeBSD.org
Wed Apr 17 16:02:59 UTC 2019
Author: emaste
Date: Wed Apr 17 16:02:57 2019
New Revision: 346315
URL: https://svnweb.freebsd.org/changeset/base/346315
Log:
cap_fileargs: add fileargs_lstat service
Add fileargs_lstat function to cap_fileargs casper service to be able to
lstat files while in capability mode. It can only lstat files given in
fileargs_init.
Submitted by: Bora Özarslan <borako.ozarslan at gmail.com>
Reviewed by: oshogbo, cem (partial)
MFC after: 3 weeks
Relnotes: Yes
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D19548
Modified:
head/lib/libcasper/services/cap_fileargs/cap_fileargs.3
head/lib/libcasper/services/cap_fileargs/cap_fileargs.c
head/lib/libcasper/services/cap_fileargs/cap_fileargs.h
Modified: head/lib/libcasper/services/cap_fileargs/cap_fileargs.3
==============================================================================
--- head/lib/libcasper/services/cap_fileargs/cap_fileargs.3 Wed Apr 17 16:00:33 2019 (r346314)
+++ head/lib/libcasper/services/cap_fileargs/cap_fileargs.3 Wed Apr 17 16:02:57 2019 (r346315)
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 12, 2018
+.Dd April 17, 2019
.Dt CAP_FILEARGS 3
.Os
.Sh NAME
@@ -33,6 +33,7 @@
.Nm fileargs_init ,
.Nm fileargs_initnv ,
.Nm fileargs_free ,
+.Nm fileargs_lstat ,
.Nm fileargs_open ,
.Nm fileargs_fopen
.Nd "library for handling files in capability mode"
@@ -43,9 +44,9 @@
.In libcasper.h
.In casper/cap_fileargs.h
.Ft "fileargs_t *"
-.Fn fileargs_init "int argc" "char *argv[]" "int flags" "mode_t mode" "cap_rights_t *rightsp"
+.Fn fileargs_init "int argc" "char *argv[]" "int flags" "mode_t mode" "cap_rights_t *rightsp" "int operations"
.Ft "fileargs_t *"
-.Fn fileargs_cinit "cap_channel_t *cas" "int argc" "char *argv[]" "int flags" "mode_t mode" "cap_rights_t *rightsp"
+.Fn fileargs_cinit "cap_channel_t *cas" "int argc" "char *argv[]" "int flags" "mode_t mode" "cap_rights_t *rightsp" "int operations"
.Ft "fileargs_t *"
.Fn fileargs_cinitnv "cap_channel_t *cas" "nvlist_t *limits"
.Ft "fileargs_t *"
@@ -53,6 +54,8 @@
.Ft "void"
.Fn fileargs_free "fileargs_t *fa"
.Ft "int"
+.Fn fileargs_lstat "fileargs_t *fa" "const char *path" "struct stat *sb"
+.Ft "int"
.Fn fileargs_open "fileargs_t *fa" "const char *name"
.Ft "FILE *"
.Fn fileargs_fopen "fileargs_t *fa" "const char *name" "const char *mode"
@@ -97,6 +100,22 @@ The
argument contains a list of the capability rights which file should be limited to.
For more details of the capability rights see
.Xr cap_rights_init 3 .
+The
+.Fa operations
+argument limits the operations that are available using
+.Nm system.fileargs .
+.Fa operations
+is a combination of:
+.Bl -ohang -offset indent
+.It FA_OPEN
+Allow
+.Fn fileargs_open
+and
+.Fn fileargs_fopen .
+.It FA_LSTAT
+Allow
+.Fn fileargs_lstat .
+.El
.Pp
The function
.Fn fileargs_cinit
@@ -126,6 +145,11 @@ The function handle
.Dv NULL
argument.
.Pp
+The function
+.Fn fileargs_lstat
+is equivalent to
+.Xr lstat 2 .
+.Pp
The functions
.Fn fileargs_open
and
@@ -165,6 +189,15 @@ must contain the
The
.Va mode
argument tells which what mode file should be created.
+.It operations (NV_TYPE_NUMBER)
+The
+.Va operations
+limits the usable operations for
+.Fa system.fileargs .
+The possible values are explained as
+.Va operations
+argument with
+.Fn fileargs_init .
.El
.Pp
The
@@ -201,7 +234,7 @@ argv += optind;
/* Create capability to the system.fileargs service. */
fa = fileargs_init(argc, argv, O_RDONLY, 0,
- cap_rights_init(&rights, CAP_READ));
+ cap_rights_init(&rights, CAP_READ), FA_OPEN);
if (fa == NULL)
err(1, "unable to open system.fileargs service");
@@ -222,6 +255,7 @@ fileargs_free(fa);
.Ed
.Sh SEE ALSO
.Xr cap_enter 2 ,
+.Xr lstat 2 ,
.Xr open 2 ,
.Xr cap_rights_init 3 ,
.Xr err 3 ,
Modified: head/lib/libcasper/services/cap_fileargs/cap_fileargs.c
==============================================================================
--- head/lib/libcasper/services/cap_fileargs/cap_fileargs.c Wed Apr 17 16:00:33 2019 (r346314)
+++ head/lib/libcasper/services/cap_fileargs/cap_fileargs.c Wed Apr 17 16:02:57 2019 (r346315)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/cnv.h>
#include <sys/dnv.h>
#include <sys/nv.h>
+#include <sys/stat.h>
#include <assert.h>
#include <errno.h>
@@ -59,8 +60,37 @@ struct fileargs {
};
static int
-fileargs_get_cache(fileargs_t *fa, const char *name)
+fileargs_get_lstat_cache(fileargs_t *fa, const char *name, struct stat *sb)
{
+ const nvlist_t *nvl;
+ size_t size;
+ const void *buf;
+
+ assert(fa != NULL);
+ assert(fa->fa_magic == FILEARGS_MAGIC);
+ assert(name != NULL);
+
+ if (fa->fa_cache == NULL)
+ return (-1);
+
+ nvl = dnvlist_get_nvlist(fa->fa_cache, name, NULL);
+ if (nvl == NULL)
+ return (-1);
+
+ if (!nvlist_exists_binary(nvl, "stat")) {
+ return (-1);
+ }
+
+ buf = nvlist_get_binary(nvl, "stat", &size);
+ assert(size == sizeof(*sb));
+ memcpy(sb, buf, size);
+
+ return (0);
+}
+
+static int
+fileargs_get_fd_cache(fileargs_t *fa, const char *name)
+{
int fd;
const nvlist_t *nvl;
nvlist_t *tnvl;
@@ -80,6 +110,12 @@ fileargs_get_cache(fileargs_t *fa, const char *name)
return (-1);
tnvl = nvlist_take_nvlist(fa->fa_cache, name);
+
+ if (!nvlist_exists_descriptor(tnvl, "fd")) {
+ nvlist_destroy(tnvl);
+ return (-1);
+ }
+
fd = nvlist_take_descriptor(tnvl, "fd");
nvlist_destroy(tnvl);
@@ -102,7 +138,7 @@ fileargs_set_cache(fileargs_t *fa, nvlist_t *nvl)
}
static nvlist_t*
-fileargs_fetch(fileargs_t *fa, const char *name)
+fileargs_fetch(fileargs_t *fa, const char *name, const char *cmd)
{
nvlist_t *nvl;
int serrno;
@@ -111,7 +147,7 @@ fileargs_fetch(fileargs_t *fa, const char *name)
assert(name != NULL);
nvl = nvlist_create(NV_FLAG_NO_UNIQUE);
- nvlist_add_string(nvl, "cmd", "open");
+ nvlist_add_string(nvl, "cmd", cmd);
nvlist_add_string(nvl, "name", name);
nvl = cap_xfer_nvlist(fa->fa_chann, nvl);
@@ -130,7 +166,7 @@ fileargs_fetch(fileargs_t *fa, const char *name)
static nvlist_t *
fileargs_create_limit(int argc, const char * const *argv, int flags,
- mode_t mode, cap_rights_t *rightsp)
+ mode_t mode, cap_rights_t *rightsp, int operations)
{
nvlist_t *limits;
int i;
@@ -140,6 +176,7 @@ fileargs_create_limit(int argc, const char * const *ar
return (NULL);
nvlist_add_number(limits, "flags", flags);
+ nvlist_add_number(limits, "operations", operations);
if (rightsp != NULL) {
nvlist_add_binary(limits, "cap_rights", rightsp,
sizeof(*rightsp));
@@ -172,7 +209,7 @@ fileargs_create(cap_channel_t *chan, int fdflags)
fileargs_t *
fileargs_init(int argc, char *argv[], int flags, mode_t mode,
- cap_rights_t *rightsp)
+ cap_rights_t *rightsp, int operations)
{
nvlist_t *limits;
@@ -181,7 +218,7 @@ fileargs_init(int argc, char *argv[], int flags, mode_
}
limits = fileargs_create_limit(argc, (const char * const *)argv, flags,
- mode, rightsp);
+ mode, rightsp, operations);
if (limits == NULL)
return (NULL);
@@ -190,7 +227,7 @@ fileargs_init(int argc, char *argv[], int flags, mode_
fileargs_t *
fileargs_cinit(cap_channel_t *cas, int argc, char *argv[], int flags,
- mode_t mode, cap_rights_t *rightsp)
+ mode_t mode, cap_rights_t *rightsp, int operations)
{
nvlist_t *limits;
@@ -199,7 +236,7 @@ fileargs_cinit(cap_channel_t *cas, int argc, char *arg
}
limits = fileargs_create_limit(argc, (const char * const *)argv, flags,
- mode, rightsp);
+ mode, rightsp, operations);
if (limits == NULL)
return (NULL);
@@ -234,7 +271,7 @@ fileargs_cinitnv(cap_channel_t *cas, nvlist_t *limits)
cap_channel_t *chann;
fileargs_t *fa;
int serrno, ret;
- int flags;
+ int flags, operations;
assert(cas != NULL);
@@ -252,6 +289,7 @@ fileargs_cinitnv(cap_channel_t *cas, nvlist_t *limits)
}
flags = nvlist_get_number(limits, "flags");
+ operations = nvlist_get_number(limits, "operations");
/* Limits are consumed no need to free them. */
ret = cap_limit_set(chann, limits);
@@ -291,11 +329,11 @@ fileargs_open(fileargs_t *fa, const char *name)
return (-1);
}
- fd = fileargs_get_cache(fa, name);
+ fd = fileargs_get_fd_cache(fa, name);
if (fd != -1)
return (fd);
- nvl = fileargs_fetch(fa, name);
+ nvl = fileargs_fetch(fa, name, "open");
if (nvl == NULL)
return (-1);
@@ -322,6 +360,53 @@ fileargs_fopen(fileargs_t *fa, const char *name, const
return (fdopen(fd, mode));
}
+int
+fileargs_lstat(fileargs_t *fa, const char *name, struct stat *sb)
+{
+ nvlist_t *nvl;
+ const void *buf;
+ size_t size;
+ char *cmd;
+
+ assert(fa != NULL);
+ assert(fa->fa_magic == FILEARGS_MAGIC);
+
+ if (name == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (sb == NULL) {
+ errno = EFAULT;
+ return (-1);
+ }
+
+ if (fa->fa_chann == NULL) {
+ errno = ENOTCAPABLE;
+ return (-1);
+ }
+
+ if (fileargs_get_lstat_cache(fa, name, sb) != -1)
+ return (0);
+
+ nvl = fileargs_fetch(fa, name, "lstat");
+ if (nvl == NULL)
+ return (-1);
+
+ buf = nvlist_get_binary(nvl, "stat", &size);
+ assert(size == sizeof(*sb));
+ memcpy(sb, buf, size);
+
+ cmd = nvlist_take_string(nvl, "cmd");
+ if (strcmp(cmd, "cache") == 0)
+ fileargs_set_cache(fa, nvl);
+ else
+ nvlist_destroy(nvl);
+ free(cmd);
+
+ return (0);
+}
+
void
fileargs_free(fileargs_t *fa)
{
@@ -348,6 +433,7 @@ static void *cacheposition;
static bool allcached;
static const cap_rights_t *caprightsp;
static int capflags;
+static int allowed_operations;
static mode_t capmode;
static int
@@ -382,6 +468,7 @@ fileargs_add_cache(nvlist_t *nvlout, const nvlist_t *l
void *cookie;
nvlist_t *new;
const char *fname;
+ struct stat sb;
if ((capflags & O_CREAT) != 0) {
allcached = true;
@@ -409,14 +496,25 @@ fileargs_add_cache(nvlist_t *nvlout, const nvlist_t *l
continue;
}
- fd = open_file(fname);
- if (fd < 0) {
- i--;
- continue;
+ new = nvlist_create(NV_FLAG_NO_UNIQUE);
+ if ((allowed_operations & FA_OPEN) != 0) {
+ fd = open_file(fname);
+ if (fd < 0) {
+ i--;
+ nvlist_destroy(new);
+ continue;
+ }
+ nvlist_move_descriptor(new, "fd", fd);
}
+ if ((allowed_operations & FA_LSTAT) != 0) {
+ if (lstat(fname, &sb) < 0) {
+ i--;
+ nvlist_destroy(new);
+ continue;
+ }
+ nvlist_add_binary(new, "stat", &sb, sizeof(sb));
+ }
- new = nvlist_create(NV_FLAG_NO_UNIQUE);
- nvlist_move_descriptor(new, "fd", fd);
nvlist_add_nvlist(nvlout, fname, new);
}
cacheposition = cookie;
@@ -424,10 +522,13 @@ fileargs_add_cache(nvlist_t *nvlout, const nvlist_t *l
}
static bool
-fileargs_allowed(const nvlist_t *limits, const nvlist_t *request)
+fileargs_allowed(const nvlist_t *limits, const nvlist_t *request, int operation)
{
const char *name;
+ if ((allowed_operations & operation) == 0)
+ return (false);
+
name = dnvlist_get_string(request, "name", NULL);
if (name == NULL)
return (false);
@@ -450,6 +551,7 @@ fileargs_limit(const nvlist_t *oldlimits, const nvlist
return (ENOTCAPABLE);
capflags = (int)dnvlist_get_number(newlimits, "flags", 0);
+ allowed_operations = (int)dnvlist_get_number(newlimits, "operations", 0);
if ((capflags & O_CREAT) != 0)
capmode = (mode_t)nvlist_get_number(newlimits, "mode");
else
@@ -461,6 +563,37 @@ fileargs_limit(const nvlist_t *oldlimits, const nvlist
}
static int
+fileargs_command_lstat(const nvlist_t *limits, nvlist_t *nvlin,
+ nvlist_t *nvlout)
+{
+ int stat;
+ const char *name;
+ struct stat sb;
+
+ if (limits == NULL)
+ return (ENOTCAPABLE);
+
+ if (!fileargs_allowed(limits, nvlin, FA_LSTAT))
+ return (ENOTCAPABLE);
+
+ name = nvlist_get_string(nvlin, "name");
+
+ stat = lstat(name, &sb);
+ if (stat < 0)
+ return (errno);
+
+ if (!allcached && (lastname == NULL ||
+ strcmp(name, lastname) == 0)) {
+ nvlist_add_string(nvlout, "cmd", "cache");
+ fileargs_add_cache(nvlout, limits, name);
+ } else {
+ nvlist_add_string(nvlout, "cmd", "lstat");
+ }
+ nvlist_add_binary(nvlout, "stat", &sb, sizeof(sb));
+ return (0);
+}
+
+static int
fileargs_command_open(const nvlist_t *limits, nvlist_t *nvlin,
nvlist_t *nvlout)
{
@@ -470,7 +603,7 @@ fileargs_command_open(const nvlist_t *limits, nvlist_t
if (limits == NULL)
return (ENOTCAPABLE);
- if (!fileargs_allowed(limits, nvlin))
+ if (!fileargs_allowed(limits, nvlin, FA_OPEN))
return (ENOTCAPABLE);
name = nvlist_get_string(nvlin, "name");
@@ -497,6 +630,9 @@ fileargs_command(const char *cmd, const nvlist_t *limi
if (strcmp(cmd, "open") == 0)
return (fileargs_command_open(limits, nvlin, nvlout));
+
+ if (strcmp(cmd, "lstat") == 0)
+ return (fileargs_command_lstat(limits, nvlin, nvlout));
return (EINVAL);
}
Modified: head/lib/libcasper/services/cap_fileargs/cap_fileargs.h
==============================================================================
--- head/lib/libcasper/services/cap_fileargs/cap_fileargs.h Wed Apr 17 16:00:33 2019 (r346314)
+++ head/lib/libcasper/services/cap_fileargs/cap_fileargs.h Wed Apr 17 16:02:57 2019 (r346315)
@@ -36,16 +36,21 @@
#include <stdbool.h>
+#define FA_OPEN 1
+#define FA_LSTAT 2
+
#ifdef WITH_CASPER
struct fileargs;
typedef struct fileargs fileargs_t;
+struct stat;
fileargs_t *fileargs_init(int argc, char *argv[], int flags, mode_t mode,
- cap_rights_t *rightsp);
+ cap_rights_t *rightsp, int operations);
fileargs_t *fileargs_cinit(cap_channel_t *cas, int argc, char *argv[],
- int flags, mode_t mode, cap_rights_t *rightsp);
+ int flags, mode_t mode, cap_rights_t *rightsp, int operations);
fileargs_t *fileargs_initnv(nvlist_t *limits);
fileargs_t *fileargs_cinitnv(cap_channel_t *cas, nvlist_t *limits);
+int fileargs_lstat(fileargs_t *fa, const char *name, struct stat *sb);
int fileargs_open(fileargs_t *fa, const char *name);
void fileargs_free(fileargs_t *fa);
FILE *fileargs_fopen(fileargs_t *fa, const char *name, const char *mode);
@@ -57,7 +62,7 @@ typedef struct fileargs {
static inline fileargs_t *
fileargs_init(int argc __unused, char *argv[] __unused, int flags, mode_t mode,
- cap_rights_t *rightsp __unused) {
+ cap_rights_t *rightsp __unused, int operations __unused) {
fileargs_t *fa;
fa = malloc(sizeof(*fa));
@@ -71,10 +76,10 @@ fileargs_init(int argc __unused, char *argv[] __unused
static inline fileargs_t *
fileargs_cinit(cap_channel_t *cas __unused, int argc, char *argv[], int flags,
- mode_t mode, cap_rights_t *rightsp)
+ mode_t mode, cap_rights_t *rightsp, int operations)
{
- return (fileargs_init(argc, argv, flags, mode, rightsp));
+ return (fileargs_init(argc, argv, flags, mode, rightsp, operations));
}
static inline fileargs_t *
@@ -85,7 +90,8 @@ fileargs_initnv(nvlist_t *limits)
fa = fileargs_init(0, NULL,
nvlist_get_number(limits, "flags"),
dnvlist_get_number(limits, "mode", 0),
- NULL);
+ NULL,
+ nvlist_get_number(limits, "operations"));
nvlist_destroy(limits);
return (fa);
@@ -98,6 +104,8 @@ fileargs_cinitnv(cap_channel_t *cas __unused, nvlist_t
return (fileargs_initnv(limits));
}
+#define fileargs_lstat(fa, name, sb) \
+ lstat(name, sb)
#define fileargs_open(fa, name) \
open(name, fa->fa_flags, fa->fa_mode)
#define fileargs_fopen(fa, name, mode) \
More information about the svn-src-all
mailing list