pf_move returns EXDEV if node not tracked
This returns EXDEV if we rename, but the second id isn't tracked. This
is likely because it was set up via fuse-bpf. Until we have a better
tracking method, we can fall back on EXDEV to handle this situation with
a copy/delete.
Bug: 202785178
Test: CtsAppSecurityHostTestCases
Test: mv /sdcard/DCIM/file /storage/emulated/0/Android/data/<pkg>/
Signed-off-by: Daniel Rosenberg <drosen@google.com>
Signed-off-by: Alessio Balsini <balsini@google.com>
Change-Id: I6e4311a75f641fc019bfad7fa26bd23398cbf252
diff --git a/jni/FuseDaemon.cpp b/jni/FuseDaemon.cpp
index 575951f..9f6d61d 100755
--- a/jni/FuseDaemon.cpp
+++ b/jni/FuseDaemon.cpp
@@ -291,6 +291,14 @@
return node::FromInode(inode, &tracker);
}
+ inline node* FromInodeNoThrow(__u64 inode) {
+ if (inode == FUSE_ROOT_ID) {
+ return root;
+ }
+
+ return node::FromInodeNoThrow(inode, &tracker);
+ }
+
inline __u64 ToInode(node* node) const {
if (IsRoot(node)) {
return FUSE_ROOT_ID;
@@ -1225,8 +1233,14 @@
return ENOENT;
}
- node* new_parent_node = fuse->FromInode(new_parent);
- if (!new_parent_node) return ENOENT;
+ node* new_parent_node;
+ if (fuse->bpf) {
+ new_parent_node = fuse->FromInodeNoThrow(new_parent);
+ if (!new_parent_node) return EXDEV;
+ } else {
+ new_parent_node = fuse->FromInode(new_parent);
+ if (!new_parent_node) return ENOENT;
+ }
const string new_parent_path = new_parent_node->BuildPath();
if (!is_app_accessible_path(fuse, new_parent_path, ctx->uid)) {
return ENOENT;
diff --git a/jni/node-inl.h b/jni/node-inl.h
index 01d6cba..c2bb260 100644
--- a/jni/node-inl.h
+++ b/jni/node-inl.h
@@ -90,6 +90,14 @@
public:
explicit NodeTracker(std::recursive_mutex* lock) : lock_(lock) {}
+ bool Exists(__u64 ino) const {
+ if (kEnableInodeTracking) {
+ const node* node = reinterpret_cast<const class node*>(ino);
+ std::lock_guard<std::recursive_mutex> guard(*lock_);
+ return active_nodes_.find(node) != active_nodes_.end();
+ }
+ }
+
void CheckTracked(__u64 ino) const {
if (kEnableInodeTracking) {
const node* node = reinterpret_cast<const class node*>(ino);
@@ -158,6 +166,12 @@
return reinterpret_cast<node*>(static_cast<uintptr_t>(ino));
}
+ // TODO(b/215235604)
+ static inline node* FromInodeNoThrow(__u64 ino, const NodeTracker* tracker) {
+ if (!tracker->Exists(ino)) return nullptr;
+ return reinterpret_cast<node*>(static_cast<uintptr_t>(ino));
+ }
+
// Maps a node to its associated inode.
static __u64 ToInode(node* node) {
return static_cast<__u64>(reinterpret_cast<uintptr_t>(node));