From abd61de52c2daa3283204e0d1e7e5a07f9fd0855 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Wed, 19 Aug 2026 18:57:37 -0700 Subject: [PATCH] S3: stamp the gateway's own uid/gid on PutObject and copy entries (#10844) * fix(s3): stamp the gateway's own ids on single-shot PutObject entries putToFiler builds the entry in the gateway now instead of proxying a PUT to the filer, and it hardcoded Uid/Gid 0 while every sibling write path stamps filer_pb.OS_UID/OS_GID. On a non-root deployment that leaves single-shot PUTs and multipart parts owned by root while directories and completed multipart objects keep the real ids, so a mount reader can list the tree but gets EACCES on every open once objects are not world-readable. * fix(s3): stamp mode and ownership on copy destinations CopyObject and UploadPartCopy build the destination attributes themselves and then assign them over the entry filer_pb.MkFile just stamped, so the copy landed with mode 0000 and uid/gid 0 - unreadable on a mount even by the filer's own user. Build the destination with the same mode PutObject resolves for the request and the gateway's own ids. --- weed/s3api/s3api_object_handlers_copy.go | 6 ++++++ weed/s3api/s3api_object_handlers_put.go | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/weed/s3api/s3api_object_handlers_copy.go b/weed/s3api/s3api_object_handlers_copy.go index 846e4b7bc..634c7aed4 100644 --- a/weed/s3api/s3api_object_handlers_copy.go +++ b/weed/s3api/s3api_object_handlers_copy.go @@ -329,6 +329,9 @@ func (s3a *S3ApiServer) CopyObjectHandler(w http.ResponseWriter, r *http.Request Mtime: t.Unix(), Crtime: entry.Attributes.Crtime, Mime: resolveDestinationMime(r.Header, entry.Attributes.Mime, replaceMeta), + FileMode: s3a.resolveFileMode(r), + Uid: filer_pb.OS_UID, + Gid: filer_pb.OS_GID, }, Extended: make(map[string][]byte), } @@ -1030,6 +1033,9 @@ func (s3a *S3ApiServer) CopyObjectPartHandler(w http.ResponseWriter, r *http.Req Mtime: t.Unix(), Crtime: t.Unix(), Mime: entry.Attributes.Mime, + FileMode: s3a.resolveFileMode(r), + Uid: filer_pb.OS_UID, + Gid: filer_pb.OS_GID, }, Extended: make(map[string][]byte), } diff --git a/weed/s3api/s3api_object_handlers_put.go b/weed/s3api/s3api_object_handlers_put.go index 5f8652ac7..6c56dc210 100644 --- a/weed/s3api/s3api_object_handlers_put.go +++ b/weed/s3api/s3api_object_handlers_put.go @@ -694,8 +694,8 @@ func (s3a *S3ApiServer) putToFiler(r *http.Request, filePath string, dataReader Crtime: now.Unix(), Mtime: now.Unix(), FileMode: fileMode, - Uid: 0, - Gid: 0, + Uid: filer_pb.OS_UID, + Gid: filer_pb.OS_GID, Mime: mimeType, FileSize: uint64(chunkResult.TotalSize), TtlSec: lifecycleTTLSec,