[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 057/108] virtiofsd: fix libfuse information leaks
From: |
Dr. David Alan Gilbert (git) |
Subject: |
[PULL 057/108] virtiofsd: fix libfuse information leaks |
Date: |
Thu, 23 Jan 2020 16:45:39 +0000 |
From: Stefan Hajnoczi <address@hidden>
Some FUSE message replies contain padding fields that are not
initialized by libfuse. This is fine in traditional FUSE applications
because the kernel is trusted. virtiofsd does not trust the guest and
must not expose uninitialized memory.
Use C struct initializers to automatically zero out memory. Not all of
these code changes are strictly necessary but they will prevent future
information leaks if the structs are extended.
Signed-off-by: Stefan Hajnoczi <address@hidden>
Reviewed-by: Daniel P. Berrangé <address@hidden>
Reviewed-by: Philippe Mathieu-Daudé <address@hidden>
Signed-off-by: Dr. David Alan Gilbert <address@hidden>
---
tools/virtiofsd/fuse_lowlevel.c | 150 ++++++++++++++++----------------
1 file changed, 76 insertions(+), 74 deletions(-)
diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c
index 2d6dc5a680..6ceb33d913 100644
--- a/tools/virtiofsd/fuse_lowlevel.c
+++ b/tools/virtiofsd/fuse_lowlevel.c
@@ -44,21 +44,23 @@ static __attribute__((constructor)) void
fuse_ll_init_pagesize(void)
static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
{
- attr->ino = stbuf->st_ino;
- attr->mode = stbuf->st_mode;
- attr->nlink = stbuf->st_nlink;
- attr->uid = stbuf->st_uid;
- attr->gid = stbuf->st_gid;
- attr->rdev = stbuf->st_rdev;
- attr->size = stbuf->st_size;
- attr->blksize = stbuf->st_blksize;
- attr->blocks = stbuf->st_blocks;
- attr->atime = stbuf->st_atime;
- attr->mtime = stbuf->st_mtime;
- attr->ctime = stbuf->st_ctime;
- attr->atimensec = ST_ATIM_NSEC(stbuf);
- attr->mtimensec = ST_MTIM_NSEC(stbuf);
- attr->ctimensec = ST_CTIM_NSEC(stbuf);
+ *attr = (struct fuse_attr){
+ .ino = stbuf->st_ino,
+ .mode = stbuf->st_mode,
+ .nlink = stbuf->st_nlink,
+ .uid = stbuf->st_uid,
+ .gid = stbuf->st_gid,
+ .rdev = stbuf->st_rdev,
+ .size = stbuf->st_size,
+ .blksize = stbuf->st_blksize,
+ .blocks = stbuf->st_blocks,
+ .atime = stbuf->st_atime,
+ .mtime = stbuf->st_mtime,
+ .ctime = stbuf->st_ctime,
+ .atimensec = ST_ATIM_NSEC(stbuf),
+ .mtimensec = ST_MTIM_NSEC(stbuf),
+ .ctimensec = ST_CTIM_NSEC(stbuf),
+ };
}
static void convert_attr(const struct fuse_setattr_in *attr, struct stat
*stbuf)
@@ -183,16 +185,16 @@ static int fuse_send_msg(struct fuse_session *se, struct
fuse_chan *ch,
int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
int count)
{
- struct fuse_out_header out;
+ struct fuse_out_header out = {
+ .unique = req->unique,
+ .error = error,
+ };
if (error <= -1000 || error > 0) {
fuse_log(FUSE_LOG_ERR, "fuse: bad error value: %i\n", error);
error = -ERANGE;
}
- out.unique = req->unique;
- out.error = error;
-
iov[0].iov_base = &out;
iov[0].iov_len = sizeof(struct fuse_out_header);
@@ -277,14 +279,16 @@ size_t fuse_add_direntry(fuse_req_t req, char *buf,
size_t bufsize,
static void convert_statfs(const struct statvfs *stbuf,
struct fuse_kstatfs *kstatfs)
{
- kstatfs->bsize = stbuf->f_bsize;
- kstatfs->frsize = stbuf->f_frsize;
- kstatfs->blocks = stbuf->f_blocks;
- kstatfs->bfree = stbuf->f_bfree;
- kstatfs->bavail = stbuf->f_bavail;
- kstatfs->files = stbuf->f_files;
- kstatfs->ffree = stbuf->f_ffree;
- kstatfs->namelen = stbuf->f_namemax;
+ *kstatfs = (struct fuse_kstatfs){
+ .bsize = stbuf->f_bsize,
+ .frsize = stbuf->f_frsize,
+ .blocks = stbuf->f_blocks,
+ .bfree = stbuf->f_bfree,
+ .bavail = stbuf->f_bavail,
+ .files = stbuf->f_files,
+ .ffree = stbuf->f_ffree,
+ .namelen = stbuf->f_namemax,
+ };
}
static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize)
@@ -328,12 +332,14 @@ static unsigned int calc_timeout_nsec(double t)
static void fill_entry(struct fuse_entry_out *arg,
const struct fuse_entry_param *e)
{
- arg->nodeid = e->ino;
- arg->generation = e->generation;
- arg->entry_valid = calc_timeout_sec(e->entry_timeout);
- arg->entry_valid_nsec = calc_timeout_nsec(e->entry_timeout);
- arg->attr_valid = calc_timeout_sec(e->attr_timeout);
- arg->attr_valid_nsec = calc_timeout_nsec(e->attr_timeout);
+ *arg = (struct fuse_entry_out){
+ .nodeid = e->ino,
+ .generation = e->generation,
+ .entry_valid = calc_timeout_sec(e->entry_timeout),
+ .entry_valid_nsec = calc_timeout_nsec(e->entry_timeout),
+ .attr_valid = calc_timeout_sec(e->attr_timeout),
+ .attr_valid_nsec = calc_timeout_nsec(e->attr_timeout),
+ };
convert_stat(&e->attr, &arg->attr);
}
@@ -362,10 +368,12 @@ size_t fuse_add_direntry_plus(fuse_req_t req, char *buf,
size_t bufsize,
fill_entry(&dp->entry_out, e);
struct fuse_dirent *dirent = &dp->dirent;
- dirent->ino = e->attr.st_ino;
- dirent->off = off;
- dirent->namelen = namelen;
- dirent->type = (e->attr.st_mode & S_IFMT) >> 12;
+ *dirent = (struct fuse_dirent){
+ .ino = e->attr.st_ino,
+ .off = off,
+ .namelen = namelen,
+ .type = (e->attr.st_mode & S_IFMT) >> 12,
+ };
memcpy(dirent->name, name, namelen);
memset(dirent->name + namelen, 0, entlen_padded - entlen);
@@ -496,15 +504,14 @@ static int fuse_send_data_iov(struct fuse_session *se,
struct fuse_chan *ch,
int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv)
{
struct iovec iov[2];
- struct fuse_out_header out;
+ struct fuse_out_header out = {
+ .unique = req->unique,
+ };
int res;
iov[0].iov_base = &out;
iov[0].iov_len = sizeof(struct fuse_out_header);
- out.unique = req->unique;
- out.error = 0;
-
res = fuse_send_data_iov(req->se, req->ch, iov, 1, bufv);
if (res <= 0) {
fuse_free_req(req);
@@ -2145,14 +2152,14 @@ static void do_destroy(fuse_req_t req, fuse_ino_t
nodeid,
static int send_notify_iov(struct fuse_session *se, int notify_code,
struct iovec *iov, int count)
{
- struct fuse_out_header out;
+ struct fuse_out_header out = {
+ .error = notify_code,
+ };
if (!se->got_init) {
return -ENOTCONN;
}
- out.unique = 0;
- out.error = notify_code;
iov[0].iov_base = &out;
iov[0].iov_len = sizeof(struct fuse_out_header);
@@ -2162,11 +2169,11 @@ static int send_notify_iov(struct fuse_session *se, int
notify_code,
int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph)
{
if (ph != NULL) {
- struct fuse_notify_poll_wakeup_out outarg;
+ struct fuse_notify_poll_wakeup_out outarg = {
+ .kh = ph->kh,
+ };
struct iovec iov[2];
- outarg.kh = ph->kh;
-
iov[1].iov_base = &outarg;
iov[1].iov_len = sizeof(outarg);
@@ -2179,17 +2186,17 @@ int fuse_lowlevel_notify_poll(struct fuse_pollhandle
*ph)
int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, fuse_ino_t ino,
off_t off, off_t len)
{
- struct fuse_notify_inval_inode_out outarg;
+ struct fuse_notify_inval_inode_out outarg = {
+ .ino = ino,
+ .off = off,
+ .len = len,
+ };
struct iovec iov[2];
if (!se) {
return -EINVAL;
}
- outarg.ino = ino;
- outarg.off = off;
- outarg.len = len;
-
iov[1].iov_base = &outarg;
iov[1].iov_len = sizeof(outarg);
@@ -2199,17 +2206,16 @@ int fuse_lowlevel_notify_inval_inode(struct
fuse_session *se, fuse_ino_t ino,
int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, fuse_ino_t
parent,
const char *name, size_t namelen)
{
- struct fuse_notify_inval_entry_out outarg;
+ struct fuse_notify_inval_entry_out outarg = {
+ .parent = parent,
+ .namelen = namelen,
+ };
struct iovec iov[3];
if (!se) {
return -EINVAL;
}
- outarg.parent = parent;
- outarg.namelen = namelen;
- outarg.padding = 0;
-
iov[1].iov_base = &outarg;
iov[1].iov_len = sizeof(outarg);
iov[2].iov_base = (void *)name;
@@ -2222,18 +2228,17 @@ int fuse_lowlevel_notify_delete(struct fuse_session
*se, fuse_ino_t parent,
fuse_ino_t child, const char *name,
size_t namelen)
{
- struct fuse_notify_delete_out outarg;
+ struct fuse_notify_delete_out outarg = {
+ .parent = parent,
+ .child = child,
+ .namelen = namelen,
+ };
struct iovec iov[3];
if (!se) {
return -EINVAL;
}
- outarg.parent = parent;
- outarg.child = child;
- outarg.namelen = namelen;
- outarg.padding = 0;
-
iov[1].iov_base = &outarg;
iov[1].iov_len = sizeof(outarg);
iov[2].iov_base = (void *)name;
@@ -2245,24 +2250,21 @@ int fuse_lowlevel_notify_delete(struct fuse_session
*se, fuse_ino_t parent,
int fuse_lowlevel_notify_store(struct fuse_session *se, fuse_ino_t ino,
off_t offset, struct fuse_bufvec *bufv)
{
- struct fuse_out_header out;
- struct fuse_notify_store_out outarg;
+ struct fuse_out_header out = {
+ .error = FUSE_NOTIFY_STORE,
+ };
+ struct fuse_notify_store_out outarg = {
+ .nodeid = ino,
+ .offset = offset,
+ .size = fuse_buf_size(bufv),
+ };
struct iovec iov[3];
- size_t size = fuse_buf_size(bufv);
int res;
if (!se) {
return -EINVAL;
}
- out.unique = 0;
- out.error = FUSE_NOTIFY_STORE;
-
- outarg.nodeid = ino;
- outarg.offset = offset;
- outarg.size = size;
- outarg.padding = 0;
-
iov[0].iov_base = &out;
iov[0].iov_len = sizeof(out);
iov[1].iov_base = &outarg;
--
2.24.1
- [PULL 047/108] virtiofsd: prevent ".." escape in lo_do_readdir(), (continued)
- [PULL 047/108] virtiofsd: prevent ".." escape in lo_do_readdir(), Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 048/108] virtiofsd: use /proc/self/fd/ O_PATH file descriptor, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 049/108] virtiofsd: sandbox mount namespace, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 045/108] virtiofsd: check input buffer size in fuse_lowlevel.c ops, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 050/108] virtiofsd: move to an empty network namespace, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 051/108] virtiofsd: move to a new pid namespace, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 053/108] virtiofsd: Parse flag FUSE_WRITE_KILL_PRIV, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 052/108] virtiofsd: add seccomp whitelist, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 054/108] virtiofsd: cap-ng helpers, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 056/108] virtiofsd: set maximum RLIMIT_NOFILE limit, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 057/108] virtiofsd: fix libfuse information leaks,
Dr. David Alan Gilbert (git) <=
- [PULL 055/108] virtiofsd: Drop CAP_FSETID if client asked for it, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 058/108] virtiofsd: add --syslog command-line option, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 059/108] virtiofsd: print log only when priority is high enough, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 063/108] virtiofsd: Handle hard reboot, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 064/108] virtiofsd: Kill threads when queues are stopped, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 060/108] virtiofsd: Add ID to the log with FUSE_LOG_DEBUG level, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 067/108] virtiofsd: passthrough_ll: add renameat2 support, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 061/108] virtiofsd: Add timestamp to the log with FUSE_LOG_DEBUG level, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 062/108] virtiofsd: Handle reinit, Dr. David Alan Gilbert (git), 2020/01/23
- [PULL 065/108] vhost-user: Print unexpected slave message types, Dr. David Alan Gilbert (git), 2020/01/23