Skip to content

DAOS-18262 common: make sure DAOS file permissions are always 0XXY#17680

Open
janekmi wants to merge 4 commits intomasterfrom
janekmi/DAOS-18262-0660
Open

DAOS-18262 common: make sure DAOS file permissions are always 0XXY#17680
janekmi wants to merge 4 commits intomasterfrom
janekmi/DAOS-18262-0660

Conversation

@janekmi
Copy link
Contributor

@janekmi janekmi commented Mar 10, 2026

At least:

  • 0660 for files
  • 0770 for directories.

So daos_server group can access DAOS files.

Guide MD-on-PMEM

daos/                           src/control/server/storage/mount/provider.go:23
├── 8ac60360-eae4-4071-86ac-a83a42dc22a3        src/mgmt/srv_target.c:699
│   ├── rdb-pool                No change
│   └── vos-X                   src/vos/vos_pool.c:1001
├── control_raft                src/control/system/raft/raft_recovery.go:93
│   ├── daos_system.db          src/control/system/raft/raft.go:269
│   └── snapshots               No change
├── daos_sys                    src/vos/sys_db.c:131
│   └── sys_db                  No change
├── NEWBORNS                    src/mgmt/srv_target.c:452
├── superblock                  src/control/common/file_utils.go:141,src/control/server/instance_superblock.go:208
└── ZOMBIES                     src/mgmt/srv_target.c:460

Guide MD-on-SSD

tree daos/
daos/                           src/control/server/storage/mount/provider.go:23
├── b4defdf5-a92f-45fe-9be0-b96122efa42d        src/mgmt/srv_target.c:699
│   ├── rdb-pool                No change
│   └── vos-X                   src/mgmt/mgmt_common.c:211
├── NEWBORNS                    src/mgmt/mgmt_common.c:134
└── ZOMBIES                     src/mgmt/mgmt_common.c:134
tree config/daos_control/
config/daos_control/            src/control/server/storage/metadata/provider.go:207
├── control_raft                src/control/system/raft/raft_recovery.go:93
│   ├── daos_system.db          src/control/system/raft/raft.go:269
│   └── snapshots               No change
│       └── 2-39-1773083440395
│           ├── meta.json
│           └── state.bin
└── engine0                     src/control/server/storage/metadata/provider.go:233
    ├── daos_nvme.conf          src/control/server/storage/bdev/backend_class.go:106
    ├── daos_sys                src/vos/sys_db.c:131
    │   └── sys_db              No change
    └── superblock              src/control/common/file_utils.go:141,src/control/server/instance_superblock.go:208

Steps for the author:

  • Commit message follows the guidelines.
  • Appropriate Features or Test-tag pragmas were used.
  • Appropriate Functional Test Stages were run.
  • At least two positive code reviews including at least one code owner from each category referenced in the PR.
  • Testing is complete. If necessary, forced-landing label added and a reason added in a comment.

After all prior steps are complete:

  • Gatekeeper requested (daos-gatekeeper added as a reviewer).

At least:

- 0660 for files
- 0770 for directories.

So daos_server group can access DAOS files.

Signed-off-by: Jan Michalski <jan-marian.michalski@hpe.com>
@janekmi janekmi requested review from a team as code owners March 10, 2026 20:32
@github-actions
Copy link

Ticket title is 'dlck command seems to require sudo privileges. Also hit the DER_NOMEM (-1009) issue.'
Status is 'Awaiting Verification'
Labels: 'test_2.8'
https://daosio.atlassian.net/browse/DAOS-18262

@janekmi janekmi requested review from rpadma2 and tanabarr March 10, 2026 21:23
src/rdb/rdb.c Outdated
path, (unsigned char *)uuid, params->rcp_size, 0 /* data_sz */, 0 /* meta_sz */,
VOS_POF_SMALL | VOS_POF_EXCL | VOS_POF_RDB | VOS_POF_EXTERNAL_CHKPT,
params->rcp_vos_df_version, &pool);
(void)umask(stored_mask);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be safer and more appropriate to do this in dss_vos_pool_create (actually why not in server_init or daos_engine's main) instead? Is rdb special in some way?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is you can put them in many different places and end up with the intended result. RDB turned out to be special because of the position I put other umask() calls so one rdb_create() call had been left unattended. But no more. I move this call a little higher up the stack so now it covers all necessary contexts. No special case for RDB. I hope you like this way. 🙂

Copy link
Contributor

@liw liw Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for responding. I'd think either one approaches the file permission problem from outside of daos_engine or even daos_server (for instance, is there any systemd setting?), or one does it in main once. It's especially concerning if one changes umask to a more permissive value (e.g., 0). That said, I've not investigated into umasks deeply myself.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since umask is per process, not per thread, changing and restoring it in target threads brings up potential questions on races among the threads---one might not want to get into such a situation.

Copy link
Contributor Author

@janekmi janekmi Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since umask is per process, not per thread, changing and restoring it in target threads brings up potential questions on races among the threads---one might not want to get into such a situation.

It is a really good point. I guess there are two possible ways out of it:

  1. Set umask(002) (instead of the default 022) first thing in main() and just keep it like this. This way you get the permissions you asked every time you create a file or directory.
  2. Always follow mkdir() and open(O_CREAT) with chmod(). So eventually you get you asked for.

I would prefer 1. Just make sure there are no 0777 used anywhere in the code. 😅

What do you think?

Thank you @grom72 for the suggestion!

@janekmi janekmi requested a review from grom72 March 11, 2026 09:42
goto out;

rc = mkdir(tca->tca_newborn, 0700);
rc = mkdir(tca->tca_newborn, 0770);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rc = mkdir(tca->tca_newborn, 0770);
rc = mkdir(tca->tca_newborn, S_IRWXU | S_IRWXG);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

const (
aioBlockSize = humanize.KiByte * 4 // device block size hardcoded to 4096 bytes
defaultAioFileMode = 0600 // AIO file permissions set to owner +rw
defaultAioFileMode = 0660 // AIO file permissions set to owner +rw
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
defaultAioFileMode = 0660 // AIO file permissions set to owner +rw
defaultAioFileMode = 0660 // AIO file permissions set to owner and group +rw

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this part of the comment since the definition has been moved to a different place. Please see DefaultFilePerm.

goto out;
}
rc = mkdir(pool_newborns_path, 0700);
rc = mkdir(pool_newborns_path, 0770);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rc = mkdir(pool_newborns_path, 0770);
rc = mkdir(pool_newborns_path, S_IRWXU | S_IRWXG);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


func createRaftDir(dbPath string) error {
if err := os.Mkdir(dbPath, 0700); err != nil && !os.IsExist(err) {
var perm os.FileMode = 0770
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please be consistent: perms := os.FileMode(0775) was used above

Suggested change
var perm os.FileMode = 0770
perms := os.FileMode(0770)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored. Please see Mkdir2().

Remove from tgt_create_preallocate() and rdb_create().
Add one in ds_mgmt_create_pool().

Signed-off-by: Jan Michalski <jan-marian.michalski@hpe.com>
@daosbuild3
Copy link
Collaborator

Test stage Functional Hardware Medium MD on SSD completed with status UNSTABLE. https://jenkins-3.daos.hpc.amslabs.hpecorp.net/job/daos-stack/job/daos//view/change-requests/job/PR-17680/2/testReport/

tanabarr
tanabarr previously approved these changes Mar 12, 2026
Copy link
Contributor

@tanabarr tanabarr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

}

if err := p.sys.Mkdir(req.DataPath, 0755); err != nil {
if err := p.sys.Mkdir(req.DataPath, perms); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given we repeat this sequence it would be nice to have a helper that performs Mkdir+Chmod to avoid the specified problem where the permissions are reduced by the umask.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed with Tom. Such a function would belong in src/control/common/file_utils.go.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Thank you guys for the idea and suggestions. Very much appreciated. 👍

src/vos/sys_db.c Outdated
static int
db_open_create(struct sys_db *db, bool try_create)
{
const mode_t db_dir_mode = 0770;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const mode_t db_dir_mode = 0770;
const mode_t db_dir_mode = S_IRWXU | S_IRWXG;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

func (p *Provider) setupDataDir(req storage.MetadataFormatRequest) error {
perms := os.FileMode(0775)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to have a constant somewhere indicating these new default perms? Same question applies at the engine level.

If we define the permission values in a C header file for the engines, we can import it in our Go package lib/daos.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not go all the way. We still use a variety of values e.g. there are directories 0770 and 0775. And I do not want to change it in this PR because I do not want to remove any permissions and I do want not grant more than it was agreed to be granted.

For now I created two constants in the Go code: DefaultFilePerm and DefaultDirPerm and I used them everywhere where the permissions were either 0770 or 0660. I left other cases unchanged.

We can discuss next steps in a separate ticket. I think the way is open assuming no opposition will come up. Please note we would have to possibly remove some permissions people were used to have. It is not obvious it would be a desirable change to have one set of permissions for all files and all directories across the project.

}

if err := p.sys.Mkdir(req.DataPath, 0755); err != nil {
if err := p.sys.Mkdir(req.DataPath, perms); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed with Tom. Such a function would belong in src/control/common/file_utils.go.


// Boltdb file permissions on create are set to 0600.
// The os.Chmod ensures the final permissions for both the user and their group are the same.
err = os.Chmod(dbCfg.DBFilePath(), 0660)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given how many places this needs to be added, I'd suggest adding SetDefaultFilePerm and SetDefaultDirPerm functions to keep the specifics of these defaults all in one place.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went a slightly different route. Please see Mkdir2(). Waiting for you thought. 🙂

janekmi added 2 commits March 16, 2026 19:56
Signed-off-by: Jan Michalski <jan-marian.michalski@hpe.com>
Add two constants and apply where possible:

- DefaultFilePerm and
- DefaultDirPerm

Define Mkdir2() as Mkdir() + Chmod().

Signed-off-by: Jan Michalski <jan-marian.michalski@hpe.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

6 participants