-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
journal: refresh cached credentials of stdout streams #13771
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
Conversation
|
@yuwata is there something I can do to help with reviewing? |
|
hmm, does this actually work? have you verified this? I am a bit surprised that this is supposed to work, I wasn't aware the SO_PASSCRED had any effect on SOCK_STREAM sockets... |
|
Hi Lennart,
Yep, I tested this by generating an image via mkosi, running that and
generating a message using systemd-cat. stracing journald shows that it
receives SCM_CREDENTIALS.
|
|
I realised that I should also force flush the existing buffer if the PID changes, so I've amended the commit. I'd like to add some sort of integration test if you can point me at some documentation / examples how to do that. It should be straight forward to use |
|
I've added an integration test which checks that this works. |
|
Ping @poettering and @yuwata. Not sure how to make the builders happy, it seems like they timed out? Otherwise this "works", but I'd appreciate your feedback. |
The failure seems to be related to this PR. |
|
@yuwata I don't think so. I just re-ran the test on my machine, and it passed: Note also that the autopkgtest for i386 and s390x pass. |
|
TEST-04 has never been flaky as far as I can remember so it looks like with this patch applied the test is less stable than usual, which most likely means that either something doesn't work as expected or the test itself is flaky. Could you force-push the code to trigger the CI once again? I think if Ubuntu CI passes, say, 5 times in a row, it will be safe to say that it's no longer flaky. I'll go ahead and add the "ci-fails" label. Could you also try running |
|
Thanks, I've added the |
|
FWIW I managed to reproduce the failure with
There's no way to look at what's going on there as far as I know (apart from downloading the artifacts from Ubuntu CI and searching for the journal files from VMs QEMU runs). In fact, at some point I think it would be great to start using `journal+console': #13719 (comment) :-) |
|
On my machine the test keeps failing intermittently with Though I don't think it has anything to do with this PR. Maybe for the time being it would make sense to move the new subtest before the part where we make sure that journald doesn't lose data. Another option would be to keep running |
|
4/5 autopkgtest passed, which I'm taking as an indication that your fix works @evverx. Thanks for helping me out. I've removed the WIP commit and pushed again, hopefully this means I'll get a clean bill of health over the weekend. CI taking more than 7 hours to run is kind of insane. |
keszybz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks nice. I'm a bit worried if the additional call to stdout_stream_scan doesn't cause confusion, but I don't think so.
test/TEST-04-JOURNAL/test-journal.sh
Outdated
| cmp /expected /output | ||
|
|
||
| # https://github.com/systemd/systemd/issues/13708 | ||
| ID=$(journalctl --new-id128 | sed -n 2p) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just systemd-id128 new.
| PID=$! | ||
| wait %% | ||
| journalctl --sync | ||
| journalctl -b -o export -t "$ID" --output-fields=_PID | grep '^_PID=' >/output |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, this should not be handled here, but isn't this a bug in journalctl? It outputs fields like __CURSOR and __REALTIME which it shouldn't. @poettering opinions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean when you say "this"? FWIW __CURSOR etc. have been output by the export format for a long time according to git blame.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW __CURSOR etc. have been output by the export format for a long time according to git blame.
Yeah, and I think this is a bug. They are written in a separate part of the code than the other fields (because they are based on the entry header, not data), and I think this was overlooked when --output-fields= was being implemented. But I don't think we can just change this at this point, because of backwards compatibility concerns.
Maybe we should add --only-fields= that would only write the specified fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to create an issue I can add a comment which references it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems we already have an issue: #5697.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/journal/journald-stream.c
Outdated
| .msg_control = buf, | ||
| .msg_controllen = sizeof(buf), | ||
| .msg_name = NULL, | ||
| .msg_namelen = 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to iniatialize .msg_name and .msg_namelen here.
src/journal/journald-stream.c
Outdated
| cmsg->cmsg_type == SCM_CREDENTIALS && | ||
| cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) | ||
| ucred = (struct ucred *)CMSG_DATA(cmsg); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{} not needed.
Please add break after ucred = is assigned. There should be only one, and we can short-circuit the loop then.
src/journal/journald-stream.c
Outdated
| if (r < 0) | ||
| goto terminate; | ||
|
|
||
| memcpy(&s->ucred, ucred, sizeof(s->ucred)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not just s->ucred = *ucred?
| * in the meantime. | ||
| */ | ||
| if (ucred && ucred->pid != s->ucred.pid) { | ||
| r = stdout_stream_scan(s, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add a comment here? i.e.
/* force out any previously half-written lines from a different process, before we switch to the new ucred structure for everything we just added */
|
two minor issues. look good to merge otherwise |
journald assumes that getsockopt(SO_PEERCRED) correctly identifies the
process on the remote end of the socket. However, this is incorrect
according to man 7 socket:
The returned credentials are those that were in effect at the
time of the call to connect(2) or socketpair(2).
This becomes a problem when a new process inherits the stdout stream
from a parent. First, log messages from the child process will
be attributed to the parent. Second, the struct ucred used by journald
becomes invalid as soon as the parent exits. Further sendmsg calls then
fail with ENOENT. Logs for the child process then vanish from the journal.
Fix this by using recvmsg on the stdout stream, and refreshing the cached
struct ucred if SCM_CREDENTIALS indicate a new process.
Fixes #13708
|
|
FWIW |
|
OK. Let's wait for the other checks to run though. |
|
CentOS CI (Arch in KVM) failed in test-journal-flush again. |
journald assumes that getsockopt(SO_PEERCRED) correctly identifies the
process on the remote end of the socket. However, this is incorrect
according to man 7 socket:
This becomes a problem when a new process inherits the stdout stream
from a parent. First, log messages from the child process will
be attributed to the parent. Second, the struct ucred used by journald
becomes invalid as soon as the parent exits. Further sendmsg calls then
fail with ENOENT. Logs for the child process then vanish from the journal.
Fix this by using recvmsg on the stdout stream, and refreshing the cached
struct ucred if SCM_CREDENTIALS indicate a new process.
Fixes #13708