Skip to content

Fix: getsockopt usage for SO_PASSCRED/SO_PASSSEC on Linux 6.16+Fix socket opts #2711

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

Open
wants to merge 2 commits into
base: criu-dev
Choose a base branch
from

Conversation

DongSunchao
Copy link

Linux 6.16 changed the behavior of getsockopt for credential-related options and it restricted SO_PASS{CRED,PIDFD,SEC} to AF_{UNIX,NETLINK,BLUETOOTH} .
This patch updates the logic to correctly handle SO_PASSCRED and SO_PASSSEC,
ensuring compatibility with newer kernels while preserving support for older ones.

Besides, /test/zdtm/static/sock_opts00.c has been changed to check the kernel version so that PF_INET can skip the SO_PASSCRED and SO_PASSSEC options.

Tested with: ./test/zdtm.py run -t zdtm/static/sock_opts00 -f ns

Fixes: #2705

Copy link
Member

@mihalicyn mihalicyn left a comment

Choose a reason for hiding this comment

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

Hi,

  1. you don't need to change anything in the test code. Test code is correct.
  2. we shouldn't introduce any checks based on a kernel version in CRIU code, except a very-very rare cases
  3. please, squash your commits and add Signed-off-by tag

@DongSunchao
Copy link
Author

Hi,

  1. you don't need to change anything in the test code. Test code is correct.
  2. we shouldn't introduce any checks based on a kernel version in CRIU code, except a very-very rare cases
  3. please, squash your commits and add Signed-off-by tag

Thank you for your advice.

  1. I have a question about the test code in /test/zdtm/static/sock_opts00.c. It currently usesPF_INETto set OPT(SO_PASSCRED) and OPT(SO_PASSSEC).However, these options are restricted to AF_{UNIX,NETLINK,BLUETOOTH}. Additionally, getsockopt() is used, which would cause an error if used to set an option like OPT(SO_PASSCRED) for a PF_INET socket. Is this the intended behavior?
  2. I have removed all kernel version checks. This raises a quesion: Should we allow PF_INET or other non- AF_{UNIX,NETLINK,BLUETOOTH} sockets to set these kernel version older than 6.16, or should this be disallowed across all kernel version? If we need different behaviors according to different kernel versions, how can we implement it without kernel version checks?
  3. Sorry, I haven't used this before. Thank you for pointing this out.

@adrianreber
Copy link
Member

Take a look at kerndat.c. That is where CRIU checks for runtime features. It is important to check for runtime features and not during compile time.

@DongSunchao DongSunchao force-pushed the fix-socket-opts branch 2 times, most recently from a036216 to 375f58e Compare August 14, 2025 09:43
@DongSunchao DongSunchao requested a review from mihalicyn August 14, 2025 10:19
@DongSunchao DongSunchao force-pushed the fix-socket-opts branch 2 times, most recently from fe790c7 to ad23fff Compare August 15, 2025 05:14
@DongSunchao DongSunchao requested a review from avagin August 15, 2025 07:11
@avagin
Copy link
Member

avagin commented Aug 15, 2025

Hi @DongSunchao , please read the contribution guidelines at https://www.kernel.org/doc/html/v4.17/process/submitting-patches.html and reformat your commits. The command git rebase -i origin/criu-dev should be helpful.

@DongSunchao DongSunchao force-pushed the fix-socket-opts branch 3 times, most recently from d8f289f to d9be15a Compare August 15, 2025 14:18
@Snorch
Copy link
Member

Snorch commented Aug 19, 2025

I somehow overlooked this one, you can look into #2719 where I have some improving ideas. Like:

  • using existing family from upper function instead of rereading it via dump_opt
  • spliting zdtm hunk to separate commit
  • using unix socket to test SO_PASSCRED/SO_PASSSEC

@DongSunchao
Copy link
Author

I somehow overlooked this one, you can look into #2719 where I have some improving ideas. Like:

  • using existing family from upper function instead of rereading it via dump_opt
  • spliting zdtm hunk to separate commit
  • using unix socket to test SO_PASSCRED/SO_PASSSEC

I've seen your code, and I really think your approach is better than mine. I'll change my code soon.

@rst0git
Copy link
Member

rst0git commented Aug 19, 2025

@DongSunchao Would it be possible to reset the author of your commits to yourself (instead of root) and use messages similar to the commits in #2719?

The following blog post provides more information on how to write good commit messages and why this is important: https://cbea.ms/git-commit/#seven-rules

@DongSunchao DongSunchao force-pushed the fix-socket-opts branch 2 times, most recently from 40a8df2 to eac71fd Compare August 19, 2025 12:04
@DongSunchao DongSunchao force-pushed the fix-socket-opts branch 2 times, most recently from 02a482c to 81f4ff5 Compare August 19, 2025 12:10
@DongSunchao
Copy link
Author

@DongSunchao Would it be possible to reset the author of your commits to yourself (instead of root) and use messages similar to the commits in #2719?

The following blog post provides more information on how to write good commit messages and why this is important: https://cbea.ms/git-commit/#seven-rules

I've made the requested changes and have done my best to follow the guidelines. However, I've run into a new issue: my code passes the Fedora Rawhide test in my repository action but fails the Vagrant Fedora Rawhide test on this PR. I'm not sure how to resolve it.

@Snorch
Copy link
Member

Snorch commented Aug 20, 2025

Having a hunk adding lines in first patch

--- a/test/zdtm/static/sock_opts00.c
+++ b/test/zdtm/static/sock_opts00.c
@@ -83,8 +83,15 @@ int main(int argc, char **argv)
                        pr_perror("can't verify %s", vname[i].name);
                        return 1;
                }
-
+               /*
+               * for kernel version >= 6.16.0 Restrict
+               * SO_PASS{CRED,PIDFD,SEC} to AF_{UNIX,NETLINK,BLUETOOTH}
+               */
                if (val[i] != rval) {
+                       if (vname[i].opt == SO_PASSCRED || vname[i].opt == SO_PASSSEC) {
+                               continue;
+                       }
+
                        errno = 0;
                        fail("%s changed: %d -> %d", vname[i].name, val[i], rval);
                        return 1;

And then having hunk removing those same lines in second patch:

@@ -78,28 +85,16 @@ int main(int argc, char **argv)
        test_waitsig();
 
        for (i = 0; i < NOPTS; i++) {
-               ret = getsockopt(sock, SOL_SOCKET, vname[i].opt, &rval, &len);
+               sk = vname[i].opt == SO_PASSCRED || vname[i].opt == SO_PASSSEC ? usock : sock;
+               ret = getsockopt(sk, SOL_SOCKET, vname[i].opt, &rval, &len);
                if (ret) {
                        pr_perror("can't verify %s", vname[i].name);
                        return 1;
                }
-               /*
-               * for kernel version >= 6.16.0 Restrict
-               * SO_PASS{CRED,PIDFD,SEC} to AF_{UNIX,NETLINK,BLUETOOTH}
-               */
-               if (val[i] != rval) {
-                       if (vname[i].opt == SO_PASSCRED || vname[i].opt == SO_PASSSEC) {
-                               continue;
-                       }
-
-                       errno = 0;
-                       fail("%s changed: %d -> %d", vname[i].name, val[i], rval);
-                       return 1;
-               }
        }
 
        pass();
        close(sock);

is generally discouraged. Please remove the hunk touching zdtm from the first patch completely.

Also by those hunks you remove important if (val[i] != rval) { value persistence check, which is not what we want, please return it.

@DongSunchao
Copy link
Author

Having a hunk adding lines in first patch

--- a/test/zdtm/static/sock_opts00.c
+++ b/test/zdtm/static/sock_opts00.c
@@ -83,8 +83,15 @@ int main(int argc, char **argv)
                        pr_perror("can't verify %s", vname[i].name);
                        return 1;
                }
-
+               /*
+               * for kernel version >= 6.16.0 Restrict
+               * SO_PASS{CRED,PIDFD,SEC} to AF_{UNIX,NETLINK,BLUETOOTH}
+               */
                if (val[i] != rval) {
+                       if (vname[i].opt == SO_PASSCRED || vname[i].opt == SO_PASSSEC) {
+                               continue;
+                       }
+
                        errno = 0;
                        fail("%s changed: %d -> %d", vname[i].name, val[i], rval);
                        return 1;

And then having hunk removing those same lines in second patch:

@@ -78,28 +85,16 @@ int main(int argc, char **argv)
        test_waitsig();
 
        for (i = 0; i < NOPTS; i++) {
-               ret = getsockopt(sock, SOL_SOCKET, vname[i].opt, &rval, &len);
+               sk = vname[i].opt == SO_PASSCRED || vname[i].opt == SO_PASSSEC ? usock : sock;
+               ret = getsockopt(sk, SOL_SOCKET, vname[i].opt, &rval, &len);
                if (ret) {
                        pr_perror("can't verify %s", vname[i].name);
                        return 1;
                }
-               /*
-               * for kernel version >= 6.16.0 Restrict
-               * SO_PASS{CRED,PIDFD,SEC} to AF_{UNIX,NETLINK,BLUETOOTH}
-               */
-               if (val[i] != rval) {
-                       if (vname[i].opt == SO_PASSCRED || vname[i].opt == SO_PASSSEC) {
-                               continue;
-                       }
-
-                       errno = 0;
-                       fail("%s changed: %d -> %d", vname[i].name, val[i], rval);
-                       return 1;
-               }
        }
 
        pass();
        close(sock);

is generally discouraged. Please remove the hunk touching zdtm from the first patch completely.

Also by those hunks you remove important if (val[i] != rval) { value persistence check, which is not what we want, please return it.

My apologies. I caught a cold last night, so I rechecked my code and fixed the other errors. Please point out any other issues you find. I'd appreciate your help.

@Snorch
Copy link
Member

Snorch commented Aug 20, 2025

Please point out any other issues you find.

I still see all the same problems with zdtm hunk and also new excess hunk 8402f8d#diff-d6b1349661211f7a79a28b685b951ce03f5919c95f404faacea6ce98692b8bf6

@DongSunchao DongSunchao force-pushed the fix-socket-opts branch 4 times, most recently from 8c7edab to 8f4e5eb Compare August 20, 2025 09:12
@DongSunchao DongSunchao requested a review from Snorch August 20, 2025 09:46
@DongSunchao DongSunchao force-pushed the fix-socket-opts branch 4 times, most recently from 5667847 to ec04868 Compare August 20, 2025 12:38
…ASSSEC

SO_PASSCRED and SO_PASSSEC are only valid for AF_UNIX and AF_NETLINK
This patch updates the test logic to use a unix socket for these options,
while preserving the original value consistency check

Fixes: checkpoint-restore#2705
Signed-off-by: Dong Sunchao <[email protected]>
Linux 6.16+ restricts SO_PASSCRED and SO_PASSSEC to AF_UNIX, AF_NETLINK, and AF_BLUETOOTH
This patch updates CRIU to check the socket family before dumping these options

Fixes: checkpoint-restore#2705
Signed-off-by: Dong Sunchao <[email protected]>
Copy link
Member

@Snorch Snorch left a comment

Choose a reason for hiding this comment

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

Looks good. Thank you!

@DongSunchao
Copy link
Author

Looks good. Thank you!

Hi, there is another issue related to the one I mentioned previously. The code fails the Vagrant Fedora Rawhide based test with an error in vdso-proxy. The specific issue is that it's creating three new VMAs and incorrectly incorporating one existing VMA. This behavior is unexpected.

However, I've tried running the same test on my local virtual machine (kernel version 6.17.0-0.rc1.250815gd7ee5bdce789.21.fc44.x86_64, Vagrant Fedora), and it passes successfully.

I find this very strange and suspect the issue might be related to the CI environment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fix sockopts handling for 6.16+ kernels
6 participants