summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Lawrence <paullawrence@google.com>2022-03-04 23:29:08 +0000
committerPaul Lawrence <paullawrence@google.com>2022-03-09 17:54:22 +0000
commita49937cdd22248a26e7aab3b9507d06abb8006cf (patch)
tree6383fec18eb2504296d7d8dd9ba1ca84ac787efe
parent137e7ff87e2503042d7cfbc360b3e4e40db6d19b (diff)
downloadMediaProvider-a49937cdd22248a26e7aab3b9507d06abb8006cf.tar.gz
Close handles
fuse-bpf kernel no longer closes the handles passed to it, so modify fuse daemon to close them. Bug: 222619123 Test: atest android.hardware.cts.CameraTest Change-Id: I3f57ba9956b671d6c9837b205a681ccde6e8dd71
-rw-r--r--jni/FuseDaemon.cpp26
1 files changed, 16 insertions, 10 deletions
diff --git a/jni/FuseDaemon.cpp b/jni/FuseDaemon.cpp
index e9890e3d2..37fc75abb 100644
--- a/jni/FuseDaemon.cpp
+++ b/jni/FuseDaemon.cpp
@@ -797,7 +797,8 @@ static bool is_app_accessible_path(struct fuse* fuse, const string& path, uid_t
return true;
}
-void fuse_bpf_fill_entries(const string& path, const int bpf_fd, struct fuse_entry_param* e) {
+void fuse_bpf_fill_entries(const string& path, const int bpf_fd, struct fuse_entry_param* e,
+ int& backing_fd) {
/*
* The file descriptor `fd` must not be closed as it is closed
* automatically by the kernel as soon as it consumes the FUSE reply. This
@@ -806,14 +807,14 @@ void fuse_bpf_fill_entries(const string& path, const int bpf_fd, struct fuse_ent
* `fd` too soon, with the risk of assigning a backing file which is either
* invalid or corresponds to the wrong file in the lower file system.
*/
- const int fd = open(path.c_str(), O_CLOEXEC | O_DIRECTORY | O_RDONLY);
- if (fd < 0) {
+ backing_fd = open(path.c_str(), O_CLOEXEC | O_DIRECTORY | O_RDONLY);
+ if (backing_fd < 0) {
PLOG(ERROR) << "Failed to open: " << path;
return;
}
e->backing_action = FUSE_ACTION_REPLACE;
- e->backing_fd = fd;
+ e->backing_fd = backing_fd;
if (bpf_fd >= 0) {
e->bpf_action = FUSE_ACTION_REPLACE;
@@ -825,21 +826,23 @@ void fuse_bpf_fill_entries(const string& path, const int bpf_fd, struct fuse_ent
}
}
-void fuse_bpf_install(struct fuse* fuse, struct fuse_entry_param* e, const string& child_path) {
+void fuse_bpf_install(struct fuse* fuse, struct fuse_entry_param* e, const string& child_path,
+ int& backing_fd) {
// TODO(b/211873756) Enable only for the primary volume. Must be
// extended for other media devices.
if (android::base::StartsWith(child_path, PRIMARY_VOLUME_PREFIX)) {
if (is_bpf_backing_path(child_path)) {
- fuse_bpf_fill_entries(child_path, fuse->bpf_fd, e);
+ fuse_bpf_fill_entries(child_path, fuse->bpf_fd, e, backing_fd);
} else if (is_package_owned_path(child_path, fuse->path)) {
- fuse_bpf_fill_entries(child_path, static_cast<int>(BpfFd::REMOVE), e);
+ fuse_bpf_fill_entries(child_path, static_cast<int>(BpfFd::REMOVE), e, backing_fd);
}
}
}
static std::regex storage_emulated_regex("^\\/storage\\/emulated\\/([0-9]+)");
static node* do_lookup(fuse_req_t req, fuse_ino_t parent, const char* name,
- struct fuse_entry_param* e, int* error_code, const FuseOp op) {
+ struct fuse_entry_param* e, int* error_code, const FuseOp op,
+ int* backing_fd = NULL) {
struct fuse* fuse = get_fuse(req);
node* parent_node = fuse->FromInode(parent);
if (!parent_node) {
@@ -874,7 +877,7 @@ static node* do_lookup(fuse_req_t req, fuse_ino_t parent, const char* name,
auto node = make_node_entry(req, parent_node, name, child_path, e, error_code, op);
- if (fuse->bpf && op == FuseOp::lookup) fuse_bpf_install(fuse, e, child_path);
+ if (fuse->bpf && op == FuseOp::lookup) fuse_bpf_install(fuse, e, child_path, *backing_fd);
return node;
}
@@ -882,14 +885,17 @@ static node* do_lookup(fuse_req_t req, fuse_ino_t parent, const char* name,
static void pf_lookup(fuse_req_t req, fuse_ino_t parent, const char* name) {
ATRACE_CALL();
struct fuse_entry_param e;
+ int backing_fd = -1;
int error_code = 0;
- if (do_lookup(req, parent, name, &e, &error_code, FuseOp::lookup)) {
+ if (do_lookup(req, parent, name, &e, &error_code, FuseOp::lookup, &backing_fd)) {
fuse_reply_entry(req, &e);
} else {
CHECK(error_code != 0);
fuse_reply_err(req, error_code);
}
+
+ if (backing_fd != -1) close(backing_fd);
}
static void do_forget(fuse_req_t req, struct fuse* fuse, fuse_ino_t ino, uint64_t nlookup) {