read_sequnlock_excl(&mount_lock);
return 0;
}
+#ifdef CONFIG_RKP_NS_PROT
+ mntget(parent->mnt);
+#else
mntget(&parent->mnt);
+#endif
mountpoint = dget(mnt->mnt_mountpoint);
read_sequnlock_excl(&mount_lock);
dput(path->dentry);
path->dentry = mountpoint;
mntput(path->mnt);
+#ifdef CONFIG_RKP_NS_PROT
+ path->mnt = parent->mnt;
+#else
path->mnt = &parent->mnt;
+#endif
return 1;
}
EXPORT_SYMBOL(follow_up);
mounted = __lookup_mnt(path->mnt, path->dentry);
if (!mounted)
break;
+#ifdef CONFIG_RKP_NS_PROT
+ path->mnt = mounted->mnt;
+ path->dentry = mounted->mnt->mnt_root;
+#else
path->mnt = &mounted->mnt;
path->dentry = mounted->mnt.mnt_root;
+#endif
nd->flags |= LOOKUP_JUMPED;
*seqp = read_seqcount_begin(&path->dentry->d_seq);
/*
unsigned seq = read_seqcount_begin(&mountpoint->d_seq);
if (unlikely(read_seqretry(&mount_lock, nd->m_seq)))
return -ECHILD;
+#ifdef CONFIG_RKP_NS_PROT
+ if (mparent->mnt == nd->path.mnt)
+#else
if (&mparent->mnt == nd->path.mnt)
+#endif
break;
/* we know that mountpoint was pinned */
nd->path.dentry = mountpoint;
+#ifdef CONFIG_RKP_NS_PROT
+ nd->path.mnt = mparent->mnt;
+#else
nd->path.mnt = &mparent->mnt;
+#endif
inode = inode2;
nd->seq = seq;
}
return -ECHILD;
if (!mounted)
break;
+#ifdef CONFIG_RKP_NS_PROT
+ nd->path.mnt = mounted->mnt;
+ nd->path.dentry = mounted->mnt->mnt_root;
+#else
nd->path.mnt = &mounted->mnt;
nd->path.dentry = mounted->mnt.mnt_root;
+#endif
inode = nd->path.dentry->d_inode;
nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
}
goto out;
switch (mode & S_IFMT) {
case 0: case S_IFREG:
- error = vfs_create2(path.mnt, path.dentry->d_inode,dentry,mode,true);
+ error = vfs_create2(path.mnt, path.dentry->d_inode, dentry, mode, true);
break;
case S_IFCHR: case S_IFBLK:
- error = vfs_mknod2(path.mnt, path.dentry->d_inode,dentry,mode,
+ error = vfs_mknod2(path.mnt, path.dentry->d_inode, dentry, mode,
new_decode_dev(dev));
break;
case S_IFIFO: case S_IFSOCK:
d_delete(dentry);
return error;
}
-EXPORT_SYMBOL(vfs_rmdir2);
-
int vfs_rmdir(struct inode *dir, struct dentry *dentry)
{
return vfs_rmdir2(NULL, dir, dentry);
struct qstr last;
int type;
unsigned int lookup_flags = 0;
+ char *path_buf = NULL;
+ char *propagate_path = NULL;
retry:
name = user_path_parent(dfd, pathname,
&path, &last, &type, lookup_flags);
error = security_path_rmdir(&path, dentry);
if (error)
goto exit3;
+ if (dentry->d_sb->s_op->unlink_callback) {
+ path_buf = kmalloc(PATH_MAX, GFP_KERNEL);
+ propagate_path = dentry_path_raw(dentry, path_buf, PATH_MAX);
+ }
error = vfs_rmdir2(path.mnt, path.dentry->d_inode, dentry);
+#ifdef CONFIG_PROC_DLOG
+ if (!error)
+ dlog_hook_rmdir(dentry, &path);
+#endif
exit3:
dput(dentry);
exit2:
mutex_unlock(&path.dentry->d_inode->i_mutex);
+ if (path_buf && !error) {
+ path.dentry->d_sb->s_op->unlink_callback(path.dentry->d_sb, propagate_path);
+ }
+ if (path_buf) {
+ kfree(path_buf);
+ path_buf = NULL;
+ }
mnt_drop_write(path.mnt);
exit1:
path_put(&path);
struct inode *inode = NULL;
struct inode *delegated_inode = NULL;
unsigned int lookup_flags = 0;
+ char *path_buf = NULL;
+ char *propagate_path = NULL;
retry:
name = user_path_parent(dfd, pathname,
&path, &last, &type, lookup_flags);
inode = dentry->d_inode;
if (d_is_negative(dentry))
goto slashes;
+ if (inode->i_sb->s_op->unlink_callback) {
+ path_buf = kmalloc(PATH_MAX, GFP_KERNEL);
+ propagate_path = dentry_path_raw(dentry, path_buf, PATH_MAX);
+ }
ihold(inode);
error = security_path_unlink(&path, dentry);
if (error)
goto exit2;
error = vfs_unlink2(path.mnt, path.dentry->d_inode, dentry, &delegated_inode);
+#ifdef CONFIG_PROC_DLOG
+ if (!error)
+ dlog_hook(dentry, inode, &path);
+#endif
exit2:
dput(dentry);
}
mutex_unlock(&path.dentry->d_inode->i_mutex);
+ if (path_buf && !error) {
+ inode->i_sb->s_op->unlink_callback(inode->i_sb, propagate_path);
+ }
+ if (path_buf) {
+ kfree(path_buf);
+ path_buf = NULL;
+ }
if (inode)
iput(inode); /* truncate the inode here */
inode = NULL;
{
int error;
bool is_dir = d_is_dir(old_dentry);
- const unsigned char *old_name;
struct inode *source = old_dentry->d_inode;
struct inode *target = new_dentry->d_inode;
bool new_is_dir = false;
unsigned max_links = new_dir->i_sb->s_max_links;
+ struct name_snapshot old_name;
/*
* Check source == target.
if (error)
return error;
- old_name = fsnotify_oldname_init(old_dentry->d_name.name);
+ take_dentry_name_snapshot(&old_name, old_dentry);
dget(new_dentry);
if (!is_dir || (flags & RENAME_EXCHANGE))
lock_two_nondirectories(source, target);
mutex_unlock(&target->i_mutex);
dput(new_dentry);
if (!error) {
- fsnotify_move(old_dir, new_dir, old_name, is_dir,
+ fsnotify_move(old_dir, new_dir, old_name.name, is_dir,
!(flags & RENAME_EXCHANGE) ? target : NULL, old_dentry);
if (flags & RENAME_EXCHANGE) {
fsnotify_move(new_dir, old_dir, old_dentry->d_name.name,
new_is_dir, NULL, new_dentry);
}
}
- fsnotify_oldname_free(old_name);
+ release_dentry_name_snapshot(&old_name);
return error;
}