return r;
}
+int Client::may_create(Inode *dir, int uid, int gid)
+{
+ if (uid < 0)
+ uid = get_uid();
+ if (gid < 0)
+ gid = get_gid();
+ RequestUserGroups groups(this, uid, gid);
+
+ int r = _getattr(dir, CEPH_STAT_CAP_MODE, uid, gid);
+ if (r < 0)
+ goto out;
+
+ r = inode_permission(dir, uid, groups, MAY_EXEC | MAY_WRITE);
+out:
+ ldout(cct, 3) << __func__ << " " << dir << " = " << r << dendl;
+ return r;
+}
+
+int Client::may_delete(Inode *dir, const char *name, int uid, int gid)
+{
+ if (uid < 0)
+ uid = get_uid();
+ if (gid < 0)
+ gid = get_gid();
+ RequestUserGroups groups(this, uid, gid);
+
+ int r = _getattr(dir, CEPH_STAT_CAP_MODE, uid, gid);
+ if (r < 0)
+ goto out;
+
+ r = inode_permission(dir, uid, groups, MAY_EXEC | MAY_WRITE);
+ if (r < 0)
+ goto out;
+
+ if (uid != 0 && (dir->mode & S_ISVTX)) {
+ InodeRef otherin;
+ r = _lookup(dir, name, &otherin, uid, gid);
+ if (r < 0)
+ goto out;
+ if (dir->uid != (uid_t)uid && otherin->uid != (uid_t)uid)
+ r = -EPERM;
+ }
+out:
+ ldout(cct, 3) << __func__ << " " << dir << " = " << r << dendl;
+ return r;
+}
+
vinodeno_t Client::_get_vino(Inode *in)
{
/* The caller must hold the client lock */
filepath path(relpath);
string name = path.last_dentry();
path.pop_dentry();
- InodeRef in;
- int r = path_walk(path, &in);
+ InodeRef dir;
+ int r = path_walk(path, &dir);
if (r < 0)
return r;
- return _mknod(in.get(), name.c_str(), mode, rdev);
+ return _mknod(dir.get(), name.c_str(), mode, rdev);
}
// symlinks
InodeRef dir;
r = path_walk(dirpath, &dir);
if (r < 0)
- return r;
+ goto out;
r = _create(dir.get(), dname.c_str(), flags, mode, &in, &fh, stripe_unit,
stripe_count, object_size, data_pool, &created);
}
tout(cct) << mode << std::endl;
tout(cct) << rdev << std::endl;
+ if (!cct->_conf->fuse_default_permissions) {
+ int r = may_create(parent, uid, gid);
+ if (r < 0)
+ return r;
+ }
+
InodeRef in;
int r = _mknod(parent, name, mode, rdev, uid, gid, &in);
if (r == 0) {
tout(cct) << name << std::endl;
tout(cct) << mode << std::endl;
+ if (!cct->_conf->fuse_default_permissions) {
+ int r = may_create(parent, uid, gid);
+ if (r < 0)
+ return r;
+ }
+
InodeRef in;
int r = _mkdir(parent, name, mode, uid, gid, &in);
if (r == 0) {
tout(cct) << name << std::endl;
tout(cct) << value << std::endl;
+ if (!cct->_conf->fuse_default_permissions) {
+ int r = may_create(parent, uid, gid);
+ if (r < 0)
+ return r;
+ }
+
InodeRef in;
int r = _symlink(parent, name, value, uid, gid, &in);
if (r == 0) {
tout(cct) << vino.ino.val << std::endl;
tout(cct) << name << std::endl;
+ if (!cct->_conf->fuse_default_permissions) {
+ int r = may_delete(in, name, uid, gid);
+ if (r < 0)
+ return r;
+ }
return _unlink(in, name, uid, gid);
}
tout(cct) << vino.ino.val << std::endl;
tout(cct) << name << std::endl;
+ if (!cct->_conf->fuse_default_permissions) {
+ int r = may_delete(in, name, uid, gid);
+ if (r < 0)
+ return r;
+ }
+
return _rmdir(in, name, uid, gid);
}
tout(cct) << vnewparent.ino.val << std::endl;
tout(cct) << newname << std::endl;
+ if (!cct->_conf->fuse_default_permissions) {
+ int r = may_delete(parent, name, uid, gid);
+ if (r < 0)
+ return r;
+ r = may_delete(newparent, newname, uid, gid);
+ if (r < 0 && r != -ENOENT)
+ return r;
+ }
+
return _rename(parent, name, newparent, newname, uid, gid);
}
return res;
}
-int Client::ll_link(Inode *parent, Inode *newparent, const char *newname,
+int Client::ll_link(Inode *in, Inode *newparent, const char *newname,
struct stat *attr, int uid, int gid)
{
Mutex::Locker lock(client_lock);
- vinodeno_t vparent = _get_vino(parent);
+ vinodeno_t vino = _get_vino(in);
vinodeno_t vnewparent = _get_vino(newparent);
- ldout(cct, 3) << "ll_link " << parent << " to " << vnewparent << " " <<
+ ldout(cct, 3) << "ll_link " << in << " to " << vnewparent << " " <<
newname << dendl;
tout(cct) << "ll_link" << std::endl;
- tout(cct) << vparent.ino.val << std::endl;
+ tout(cct) << vino.ino.val << std::endl;
tout(cct) << vnewparent << std::endl;
tout(cct) << newname << std::endl;
+ int r = 0;
InodeRef target;
- int r = _link(parent, newparent, newname, uid, gid, &target);
+
+ if (!cct->_conf->fuse_default_permissions) {
+ if (S_ISDIR(in->mode)) {
+ r = -EPERM;
+ goto out;
+ }
+ r = may_create(newparent, uid, gid);
+ if (r < 0)
+ goto out;
+ }
+
+ r = _link(in, newparent, newname, uid, gid, &target);
if (r == 0) {
assert(target);
fill_stat(target, attr);
_ll_get(target.get());
}
+out:
return r;
}
if (r == 0 && (flags & O_CREAT) && (flags & O_EXCL))
return -EEXIST;
- if (r == -ENOENT && (flags & O_CREAT)) {
- r = _create(parent, name, flags, mode, &in, fhp /* may be NULL */,
+ if (r == -ENOENT && (flags & O_CREAT)) {
+ if (!cct->_conf->fuse_default_permissions) {
+ r = may_create(parent, uid, gid);
+ if (r < 0)
+ goto out;
+ }
+ r = _create(parent, name, flags, mode, &in, fhp /* may be NULL */,
0, 0, 0, NULL, &created, uid, gid);
if (r < 0)
goto out;