Skip to content

Commit

Permalink
add setup for new permissions APIs
Browse files Browse the repository at this point in the history
snapshot2 adds the following for working with file permissions:

- A permissions data type representing read, write,
  execute, and "private" permissions.
- path_permissions_set() which is similar to
  fchmodat().
- fd_permissions_set() which is similar to
  fchmod().
- Two new rights for calling the two new functions.
- A permissions field added to the filestat type.
- A permissions argument passed to path_open().

This will need to be verified against the wasi-libc once the
changes land there. Based on the auto-generated WASI docs, it
seems likely that existing constants will change/break.

Refs: #59
  • Loading branch information
cjihrig committed Apr 20, 2020
1 parent 1243e5e commit 5fc0b7e
Show file tree
Hide file tree
Showing 10 changed files with 225 additions and 5 deletions.
96 changes: 96 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ This section has been adapted from the official WASI API documentation.
- [`uvwasi_fd_filestat_get()`](#fd_filestat_get)
- [`uvwasi_fd_filestat_set_size()`](#fd_filestat_set_size)
- [`uvwasi_fd_filestat_set_times()`](#fd_filestat_set_times)
- [`uvwasi_fd_permissions_set()`](#fd_permissions_set)
- [`uvwasi_fd_pread()`](#fd_pread)
- [`uvwasi_fd_prestat_get()`](#fd_prestat_get)
- [`uvwasi_fd_prestat_dir_name()`](#fd_prestat_dir_name)
Expand All @@ -237,6 +238,7 @@ This section has been adapted from the official WASI API documentation.
- [`uvwasi_path_filestat_set_times()`](#path_filestat_set_times)
- [`uvwasi_path_link()`](#path_link)
- [`uvwasi_path_open()`](#path_open)
- [`uvwasi_path_permissions_set()`](#path_permissions_set)
- [`uvwasi_path_readlink()`](#path_readlink)
- [`uvwasi_path_remove_directory()`](#path_remove_directory)
- [`uvwasi_path_rename()`](#path_rename)
Expand Down Expand Up @@ -531,6 +533,27 @@ Inputs:

A bitmask indicating which timestamps to adjust.

### <a href="#fd_permissions_set" name="fd_permissions_set"></a>`uvwasi_fd_permissions_set()`

Set the permissions of a file or directory.

This sets the permissions associated with a file or directory
in a filesystem at the time it is called. The ability to actually
access a file or directory may depend on additional permissions not
reflected here.

Note: This is similar `fchmod` in POSIX.

Inputs:

- <a href="#fd_permissions_set.fd" name="fd_permissions_set.fd"></a><code>[\_\_wasi\_fd\_t](#fd) <strong>fd</strong></code>

The file descriptor to operate on.

- <a href="#fd_permissions_set.permissions" name="fd_permissions_set.permissions"></a><code>[\_\_wasi\_permissions\_t](#permissions) <strong>permissions</strong></code>

The permissions associated with the file.

### <a href="#fd_pread" name="fd_pread"></a>`uvwasi_fd_pread()`

Read from a file descriptor, without using and updating the
Expand Down Expand Up @@ -927,13 +950,50 @@ Inputs:

The initial flags of the file descriptor.

- <a href="#path_open.permissions" name="path_open.permissions"></a><code>[\_\_wasi\_permissions\_t](#permissions) <strong>permissions</strong></code>

If a file is created, the filesystem permissions to associate with it.

Outputs:

- <a href="#path_open.fd" name="path_open.fd"></a><code>[\_\_wasi\_fd\_t](#fd) <strong>fd</strong></code>

The file descriptor of the file that has been
opened.

### <a href="#path_permissions_set" name="path_permissions_set"></a>`uvwasi_path_permissions_set()`

Set the permissions of a file or directory.

This sets the permissions associated with a file or directory in a
filesystem at the time it is called. The ability to actually access
a file or directory may depend on additional permissions not reflected
here.

Note: This is similar `fchmodat` in POSIX.

Unlike POSIX, this doesn't expose a user/group/other distinction;
implementations in POSIX environments are suggested to consult the
umask to determine which of the user/group/other flags to modify.

Inputs:

- <a href="#path_permissions_set.fd" name="path_permissions_set.fd"></a><code>[\_\_wasi\_fd\_t](#fd) <strong>fd</strong></code>

The file descriptor to operate on.

- <a href="#path_permissions_set.flags" name="path_permissions_set.flags"></a><code>[\_\_wasi\_lookupflags\_t](#lookupflags) <strong>flags</strong></code>

Flags determining the method of how the path is resolved.

- <a href="#path_permissions_set.path" name="path_permissions_set.path"></a><code>const char \*<strong>path</strong></code> and <a href="#path_permissions_set.path_len" name="path_permissions_set.path_len"></a><code>size\_t <strong>path\_len</strong></code>

The path to a file to query.

- <a href="#path_permissions_set.permissions" name="path_permissions_set.permissions"></a><code>[\_\_wasi\_permissions\_t](#permissions) <strong>permissions</strong></code>

The permissions associated with the file.

### <a href="#path_readlink" name="path_readlink"></a>`uvwasi_path_readlink()`

Read the contents of a symbolic link.
Expand Down Expand Up @@ -1809,6 +1869,10 @@ Members:

File type.

- <a href="#filestat.permissions" name="filestat.permissions"></a><code>[\_\_wasi\_permissions\_t](#permissions) <strong>permissions</strong></code>

File permissions.

- <a href="#filestat.st_nlink" name="filestat.st_nlink"></a><code>[\_\_wasi\_linkcount\_t](#linkcount) <strong>st\_nlink</strong></code>

Number of hard links to the file.
Expand Down Expand Up @@ -1971,6 +2035,30 @@ Possible values:

Truncate file to size 0.

### <a href="#permissions" name="permissions"></a>`uvwasi_permissions_t` (`uint8_t` bitfield)

File permissions. This represents the permissions associated with a file in a filesystem, and don't fully reflect all the conditions which determine whether a given WASI program can access the file.

Possible values:

- <a href="#permissions.read" name="permissions.read"></a>**`UVWASI_PERMISSION_READ`**

For files, permission to read the file. For directories, permission to do `readdir` and access files within the directory.

Note: This is similar to the read bit being set on files, and the read *and* execute bits being set on directories, in POSIX.

- <a href="#permissions.write" name="permissions.write"></a>**`UVWASI_PERMISSION_WRITE`**

For files, permission to mutate the file. For directories, permission to create, remove, and rename items within the directory.

- <a href="#permissions.execute" name="permissions.execute"></a>**`UVWASI_PERMISSION_EXECUTE`**

For files, permission to "execute" the file, using whatever concept of "executing" the host filesystem has. This flag is not valid for directories.

- <a href="#permissions.private" name="permissions.private"></a>**`UVWASI_PERMISSION_PRIVATE`**

For filesystems which have a concept of multiple "users", this flag indicates that the file is only accessible by the effective "user" that the WASI store uses to access the filesystem, and inaccessible to other "users".

### <a href="#riflags" name="riflags"></a>`uvwasi_riflags_t` (`uint16_t` bitfield)

Flags provided to [`uvwasi_sock_recv()`](#sock_recv).
Expand Down Expand Up @@ -2106,6 +2194,10 @@ Possible values:

The right to invoke [`uvwasi_path_filestat_set_times()`](#path_filestat_set_times).

- <a href="#rights.path_permissions_set" name="rights.path_permissions_set"></a>**`UVWASI_RIGHT_PATH_PERMISSIONS_SET`**

The right to invoke [`uvwasi_path_filestat_permissions_set()`](#path_filestat_permissions_set).

- <a href="#rights.fd_filestat_get" name="rights.fd_filestat_get"></a>**`UVWASI_RIGHT_FD_FILESTAT_GET`**

The right to invoke [`uvwasi_fd_filestat_get()`](#fd_filestat_get).
Expand All @@ -2118,6 +2210,10 @@ Possible values:

The right to invoke [`uvwasi_fd_filestat_set_times()`](#fd_filestat_set_times).

- <a href="#rights.fd_permissions_set" name="rights.fd_permissions_set"></a>**`UVWASI_RIGHT_FD_PERMISSIONS_SET`**

The right to invoke [`uvwasi_fd_filestat_permissions_set()`](#fd_filestat_permissions_set).

- <a href="#rights.path_symlink" name="rights.path_symlink"></a>**`UVWASI_RIGHT_PATH_SYMLINK`**

The right to invoke [`uvwasi_path_symlink()`](#path_symlink).
Expand Down
10 changes: 10 additions & 0 deletions include/uvwasi.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi,
uvwasi_timestamp_t st_atim,
uvwasi_timestamp_t st_mtim,
uvwasi_fstflags_t fst_flags);
uvwasi_errno_t uvwasi_fd_permissions_set(uvwasi_t* uvwasi,
uvwasi_fd_t fd,
uvwasi_permissions_t permissions);
uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi,
uvwasi_fd_t fd,
const uvwasi_iovec_t* iovs,
Expand Down Expand Up @@ -208,7 +211,14 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi,
uvwasi_rights_t fs_rights_base,
uvwasi_rights_t fs_rights_inheriting,
uvwasi_fdflags_t fs_flags,
uvwasi_permissions_t permissions,
uvwasi_fd_t* fd);
uvwasi_errno_t uvwasi_path_permissions_set(uvwasi_t* uvwasi,
uvwasi_fd_t fd,
uvwasi_lookupflags_t flags,
const char* path,
size_t path_len,
uvwasi_permissions_t permissions);
uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi,
uvwasi_fd_t fd,
const char* path,
Expand Down
9 changes: 9 additions & 0 deletions include/wasi_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,18 @@ typedef uint64_t uvwasi_rights_t; /* Bitfield */
#define UVWASI_RIGHT_PATH_UNLINK_FILE (1 << 26)
#define UVWASI_RIGHT_POLL_FD_READWRITE (1 << 27)
#define UVWASI_RIGHT_SOCK_SHUTDOWN (1 << 28)
#define UVWASI_RIGHT_PATH_PERMISSIONS_SET (1 << 29)
#define UVWASI_RIGHT_FD_PERMISSIONS_SET (1 << 30)

typedef uint16_t uvwasi_roflags_t; /* Bitfield */
#define UVWASI_SOCK_RECV_DATA_TRUNCATED (1 << 0)

typedef uint8_t uvwasi_permissions_t; /* Bitfield */
#define UVWASI_PERMISSION_READ (1 << 0)
#define UVWASI_PERMISSION_WRITE (1 << 1)
#define UVWASI_PERMISSION_EXECUTE (1 << 2)
#define UVWASI_PERMISSION_PRIVATE (1 << 3)

typedef uint8_t uvwasi_sdflags_t; /* Bitfield */
#define UVWASI_SHUT_RD (1 << 0)
#define UVWASI_SHUT_WR (1 << 1)
Expand Down Expand Up @@ -264,6 +272,7 @@ typedef struct uvwasi_filestat_s {
uvwasi_device_t st_dev;
uvwasi_inode_t st_ino;
uvwasi_filetype_t st_filetype;
uvwasi_permissions_t permissions;
uvwasi_linkcount_t st_nlink;
uvwasi_filesize_t st_size;
uvwasi_timestamp_t st_atim;
Expand Down
8 changes: 8 additions & 0 deletions src/uv_mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,14 @@ void uvwasi__stat_to_filestat(const uv_stat_t* stat, uvwasi_filestat_t* fs) {
fs->st_atim = uvwasi__timespec_to_timestamp(&stat->st_atim);
fs->st_mtim = uvwasi__timespec_to_timestamp(&stat->st_mtim);
fs->st_ctim = uvwasi__timespec_to_timestamp(&stat->st_ctim);
/* TODO(cjihrig): Permissions are not currently used. */
fs->permissions = 0;
}


void uvwasi__permissions_to_mode(const uvwasi_permissions_t permissions,
int* mode) {
*mode = 0666; /* TODO(cjihrig): Parse this from permissions argument. */
}


Expand Down
2 changes: 2 additions & 0 deletions src/uv_mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ uvwasi_errno_t uvwasi__translate_uv_error(int err);
uvwasi_timestamp_t uvwasi__timespec_to_timestamp(const uv_timespec_t* ts);
uvwasi_filetype_t uvwasi__stat_to_filetype(const uv_stat_t* stat);
void uvwasi__stat_to_filestat(const uv_stat_t* stat, uvwasi_filestat_t* fs);
void uvwasi__permissions_to_mode(const uvwasi_permissions_t permissions,
int* mode);
uvwasi_errno_t uvwasi__get_filetype_by_fd(uv_file fd, uvwasi_filetype_t* type);

#endif /* __UVWASI_UV_MAPPING_H__ */
84 changes: 83 additions & 1 deletion src/uvwasi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,38 @@ uvwasi_errno_t uvwasi_fd_filestat_set_times(uvwasi_t* uvwasi,
}


uvwasi_errno_t uvwasi_fd_permissions_set(uvwasi_t* uvwasi,
uvwasi_fd_t fd,
uvwasi_permissions_t permissions) {
struct uvwasi_fd_wrap_t* wrap;
uv_fs_t req;
uvwasi_errno_t err;
int mode;
int r;

if (uvwasi == NULL)
return UVWASI_EINVAL;

uvwasi__permissions_to_mode(permissions, &mode);
err = uvwasi_fd_table_get(&uvwasi->fds,
fd,
&wrap,
UVWASI_RIGHT_FD_PERMISSIONS_SET,
0);
if (err != UVWASI_ESUCCESS)
return err;

r = uv_fs_fchmod(NULL, &req, wrap->fd, mode, NULL);
uv_mutex_unlock(&wrap->mutex);
uv_fs_req_cleanup(&req);

if (r != 0)
return uvwasi__translate_uv_error(r);

return UVWASI_ESUCCESS;
}


uvwasi_errno_t uvwasi_fd_pread(uvwasi_t* uvwasi,
uvwasi_fd_t fd,
const uvwasi_iovec_t* iovs,
Expand Down Expand Up @@ -1864,6 +1896,7 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi,
uvwasi_rights_t fs_rights_base,
uvwasi_rights_t fs_rights_inheriting,
uvwasi_fdflags_t fs_flags,
uvwasi_permissions_t permissions,
uvwasi_fd_t* fd) {
char resolved_path[PATH_MAX_BYTES];
uvwasi_rights_t needed_inheriting;
Expand All @@ -1878,11 +1911,13 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi,
int flags;
int read;
int write;
int mode;
int r;

if (uvwasi == NULL || path == NULL || fd == NULL)
return UVWASI_EINVAL;

uvwasi__permissions_to_mode(permissions, &mode);
read = 0 != (fs_rights_base & (UVWASI_RIGHT_FD_READ |
UVWASI_RIGHT_FD_READDIR));
write = 0 != (fs_rights_base & (UVWASI_RIGHT_FD_DATASYNC |
Expand Down Expand Up @@ -1948,7 +1983,7 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi,
return err;
}

r = uv_fs_open(NULL, &req, resolved_path, flags, 0666, NULL);
r = uv_fs_open(NULL, &req, resolved_path, flags, mode, NULL);
uv_mutex_unlock(&dirfd_wrap->mutex);
uv_fs_req_cleanup(&req);

Expand Down Expand Up @@ -1995,6 +2030,53 @@ uvwasi_errno_t uvwasi_path_open(uvwasi_t* uvwasi,
}


uvwasi_errno_t uvwasi_path_permissions_set(uvwasi_t* uvwasi,
uvwasi_fd_t fd,
uvwasi_lookupflags_t flags,
const char* path,
size_t path_len,
uvwasi_permissions_t permissions) {
char resolved_path[PATH_MAX_BYTES];
struct uvwasi_fd_wrap_t* wrap;
uv_fs_t req;
uvwasi_errno_t err;
int mode;
int r;

if (uvwasi == NULL || path == NULL)
return UVWASI_EINVAL;

uvwasi__permissions_to_mode(permissions, &mode);
err = uvwasi_fd_table_get(&uvwasi->fds,
fd,
&wrap,
UVWASI_RIGHT_PATH_PERMISSIONS_SET,
0);
if (err != UVWASI_ESUCCESS)
return err;

err = uvwasi__resolve_path(uvwasi,
wrap,
path,
path_len,
resolved_path,
flags);
if (err != UVWASI_ESUCCESS) {
uv_mutex_unlock(&wrap->mutex);
return err;
}

r = uv_fs_chmod(NULL, &req, resolved_path, mode, NULL);
uv_mutex_unlock(&wrap->mutex);
uv_fs_req_cleanup(&req);

if (r != 0)
return uvwasi__translate_uv_error(r);

return UVWASI_ESUCCESS;
}


uvwasi_errno_t uvwasi_path_readlink(uvwasi_t* uvwasi,
uvwasi_fd_t fd,
const char* path,
Expand Down
5 changes: 5 additions & 0 deletions src/wasi_rights.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
UVWASI_RIGHT_PATH_FILESTAT_GET | \
UVWASI_RIGHT_PATH_FILESTAT_SET_SIZE | \
UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES | \
UVWASI_RIGHT_PATH_PERMISSIONS_SET | \
UVWASI_RIGHT_FD_FILESTAT_GET | \
UVWASI_RIGHT_FD_FILESTAT_SET_TIMES | \
UVWASI_RIGHT_FD_FILESTAT_SET_SIZE | \
UVWASI_RIGHT_FD_PERMISSIONS_SET | \
UVWASI_RIGHT_PATH_SYMLINK | \
UVWASI_RIGHT_PATH_UNLINK_FILE | \
UVWASI_RIGHT_PATH_REMOVE_DIRECTORY | \
Expand All @@ -51,6 +53,7 @@
UVWASI_RIGHT_FD_FILESTAT_GET | \
UVWASI_RIGHT_FD_FILESTAT_SET_SIZE | \
UVWASI_RIGHT_FD_FILESTAT_SET_TIMES |\
UVWASI_RIGHT_FD_PERMISSIONS_SET | \
UVWASI_RIGHT_POLL_FD_READWRITE)
#define UVWASI__RIGHTS_REGULAR_FILE_INHERITING 0

Expand All @@ -69,8 +72,10 @@
UVWASI_RIGHT_PATH_FILESTAT_GET | \
UVWASI_RIGHT_PATH_FILESTAT_SET_SIZE | \
UVWASI_RIGHT_PATH_FILESTAT_SET_TIMES | \
UVWASI_RIGHT_PATH_PERMISSIONS_SET | \
UVWASI_RIGHT_FD_FILESTAT_GET | \
UVWASI_RIGHT_FD_FILESTAT_SET_TIMES | \
UVWASI_RIGHT_FD_PERMISSIONS_SET | \
UVWASI_RIGHT_PATH_SYMLINK | \
UVWASI_RIGHT_PATH_UNLINK_FILE | \
UVWASI_RIGHT_PATH_REMOVE_DIRECTORY | \
Expand Down
Loading

0 comments on commit 5fc0b7e

Please sign in to comment.