Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support setting socket permissions #12211

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

DamianZaremba
Copy link

@DamianZaremba DamianZaremba commented May 11, 2024

Currently the socket is created with 755, which prevents potentially prevents other users from accessing the socket.

This change adds the env variable SOCKET_PATH_MASK, which if specified explicitly chmod's the specified socket path, allowing unrestricted access if required.


Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.

Tests

  • Run the tests with pnpm test and lint the project with pnpm lint and pnpm check

Changesets

  • If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpm changeset and following the prompts. Changesets that add features should be minor and those that fix bugs should be patch. Please prefix changeset messages with feat:, fix:, or chore:.

Edits

  • Please ensure that 'Allow edits from maintainers' is checked. PRs without this option may be closed.

Copy link

changeset-bot bot commented May 11, 2024

🦋 Changeset detected

Latest commit: ba78b11

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sveltejs/adapter-node Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@benmccann
Copy link
Member

I don't quite understand when you would use this new option. Also, the docs would need to be updated to include a mention of it

Current the socket is created based on the umask (commonly `0022`),
resulting in read only sockets.

This change adds the env variable `0022`, which configures
`writableAll`, supporting writable sockets.
@DamianZaremba
Copy link
Author

I don't quite understand when you would use this new option. Also, the docs would need to be updated to include a mention of it

I have a setup where multiple applications are run in containers (podman) with directories mounted onto the host, through which unix sockets are made available.

Currently, the socket from node is not accessible by non-root users;

damian@srv1:~$ curl --unix-socket /run/xxx.com/test.socket http://xxx.com; echo
curl: (7) Couldn't connect to server

damian@srv1:~$ sudo curl --unix-socket /run/xxx.com/test.socket http://xxx.com; echo
Not Found

A minimal reproduction of what is happening;

$ podman run -ti node:alpine sh
/ # mkdir app && cd app && npm install polka

/app # cat > index.js <<'EOF'
> const polka = require('polka');
> let path = '/tmp/test.socket';
> let host = '0.0.0.0';
> let port = false;
> polka().listen({ path, host, port });
> EOF

/app # node . &

/app # ls -lra /tmp/test.socket
srwxr-xr-x    1 root     root             0 May 16 10:33 /tmp/test.socket

As test.socket is not writable, requests cannot be sent to it from other users.

Digging through the layers;

  1. polka.listen passes through to http.Server.listen
  2. http.Server.listen has the same signature as net.Server.listen
  3. net.Server.listen ends up calling into node/lib/net.js:createServerHandle
  4. createServerHandle creates a Pipe object from pipe_wrap
  5. pipe_wrap calls uv_pipe_bind2 from libuv
  6. uv_pipe_bind2 calls uv__socket (which calls socket) and bind which handles actually creating the socket

On unix to set the file permissions normally you call fchmod, uv uses chmod instead, which is exposed in Pipe.

Digging back into Server.prototype.listen, if writableAll is specified then fchmod is called which sorts out the permissions via (eventually) uv.

A better solution;

Since polka is passing everything through to server.listen and writableAll is an option on server.listen we can skip calling chmod explicitly.

/app # diff original.js index.js
--- original.js
+++ index.js
@@ -2,4 +2,5 @@
 let path = '/tmp/test.socket';
 let host = '0.0.0.0';
 let port = false;
-polka().listen({ path, host, port });
+let writableAll = true;
+polka().listen({ path, host, port, writableAll });

This creates the socket with writable permissions;

/app # ls -lra /tmp/test.socket
srwxrwxrwx    1 1107     1107             0 May 16 11:15 /tmp/test.socket
damian@srv1:~$ curl --unix-socket /run/xxx.com/test.socket http://xxx.com; echo
Not Found

I've made this same change and update the documentation.

Hopefully that all makes sense and the change is sensible.

@eltigerchino eltigerchino changed the title adapter-node - support setting socket permissions feat: support setting socket permissions May 16, 2024
@eltigerchino eltigerchino added the feature request New feature or request label May 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants