Skip to content

Commit

Permalink
fusefs: respect RLIMIT_FSIZE during truncate
Browse files Browse the repository at this point in the history
PR:		164793
MFC after:	2 weeks
Reviewed by:	kib
Differential Revision:	https://reviews.freebsd.org/D36703
  • Loading branch information
asomers committed Sep 25, 2022
1 parent 550e01c commit 0a192b3
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
3 changes: 3 additions & 0 deletions sys/fs/fuse/fuse_vnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -2248,6 +2248,9 @@ fuse_vnop_setattr(struct vop_setattr_args *ap)
case VREG:
if (vfs_isrdonly(mp))
return (EROFS);
err = vn_rlimit_trunc(vap->va_size, td);
if (err)
return (err);
break;
default:
/*
Expand Down
44 changes: 43 additions & 1 deletion tests/sys/fs/fusefs/setattr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,30 @@
*/

extern "C" {
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/time.h>

#include <fcntl.h>
#include <semaphore.h>
#include <signal.h>
}

#include "mockfs.hh"
#include "utils.hh"

using namespace testing;

class Setattr : public FuseTest {};
class Setattr : public FuseTest {
public:
static sig_atomic_t s_sigxfsz;
};

class RofsSetattr: public Setattr {
public:
virtual void SetUp() {
s_sigxfsz = 0;
m_ro = true;
Setattr::SetUp();
}
Expand All @@ -61,6 +69,12 @@ virtual void SetUp() {
};


sig_atomic_t Setattr::s_sigxfsz = 0;

void sigxfsz_handler(int __unused sig) {
Setattr::s_sigxfsz = 1;
}

/*
* If setattr returns a non-zero cache timeout, then subsequent VOP_GETATTRs
* should use the cached attributes, rather than query the daemon
Expand Down Expand Up @@ -553,6 +567,34 @@ TEST_F(Setattr, truncate_discards_cached_data) {
leak(fd);
}

/* truncate should fail if it would cause the file to exceed RLIMIT_FSIZE */
TEST_F(Setattr, truncate_rlimit_rsize)
{
const char FULLPATH[] = "mountpoint/some_file.txt";
const char RELPATH[] = "some_file.txt";
struct rlimit rl;
const uint64_t ino = 42;
const uint64_t oldsize = 0;
const uint64_t newsize = 100'000'000;

EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH)
.WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto& out) {
SET_OUT_HEADER_LEN(out, entry);
out.body.entry.attr.mode = S_IFREG | 0644;
out.body.entry.nodeid = ino;
out.body.entry.attr.size = oldsize;
})));

rl.rlim_cur = newsize / 2;
rl.rlim_max = 10 * newsize;
ASSERT_EQ(0, setrlimit(RLIMIT_FSIZE, &rl)) << strerror(errno);
ASSERT_NE(SIG_ERR, signal(SIGXFSZ, sigxfsz_handler)) << strerror(errno);

EXPECT_EQ(-1, truncate(FULLPATH, newsize));
EXPECT_EQ(EFBIG, errno);
EXPECT_EQ(1, s_sigxfsz);
}

/* Change a file's timestamps */
TEST_F(Setattr, utimensat) {
const char FULLPATH[] = "mountpoint/some_file.txt";
Expand Down

0 comments on commit 0a192b3

Please sign in to comment.