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

init: optionally load the system SELinux policy #400

Open
wants to merge 53 commits into
base: master
Choose a base branch
from

Conversation

WavyEbuilder
Copy link

Implements #399 . Currently a draft PR for some of the reasons noted in that issue. Another thing to add:

  • I saw mentioned here, Replace use of iostream-based classes #240 (comment), that you don't want to be falling back to C interfaces. For now, I'm just calling fprintf if the SELinux policy fails to load (as /dev/console is likely unable to be accessed at that point). Would you prefer std::cout to be used for now in this case?

@WavyEbuilder WavyEbuilder force-pushed the master branch 2 times, most recently from 5952f94 to 35df218 Compare October 15, 2024 20:53
@WavyEbuilder
Copy link
Author

Current TODO (just to note I am aware of it) is to link against libselinux in the Makefile.

@WavyEbuilder
Copy link
Author

I've added an --enable--selinux option to the configure script, however I am not really sure how best to go about linking against libselinux as it is an optional dependency. Any advice in this regard?

@WavyEbuilder
Copy link
Author

Think I've got that sorted by passing a linker flag.

@davmac314
Copy link
Owner

I will review properly when I get a chance. I don't know a heap about SELinux so bare with me. A couple of things I will point out now though:

  • Definitely avoid using fprintf, it's best if you can keep to the conventions already used throughout. cerr would normally be the right option for a definite error message, however, output should generally go via the log interface instead of directly via cout/cerr. Eg log(loglevel_t::ERROR, "(error message here)") possibly followed by flush_log() if this is before a call to exit().
  • I'm not a fan of the re-exec approach either. If the correct label can be assigned to the already-running executable (i.e. what systemd apparently does), it seems like we should just do that.
  • I'm inclined to think that there should either be a command-line option to disable loading the policy, or that should be the default and there should a command-line option to enable it.
  • Probably the whole setup should be moved to its own separate function

@WavyEbuilder
Copy link
Author

WavyEbuilder commented Oct 16, 2024

Hey! Appreciate the fast response.

Definitely avoid using fprintf, it's best if you can keep to the conventions already used throughout. cerr would normally be the right option for a definite error message, however, output should generally go via the log interface instead of directly via cout/cerr. Eg log(loglevel_t::ERROR, "(error message here)") possibly followed by flush_log() if this is before a call to exit().

A lot of the other init systems mentioned /dev/console not being available at that point in time (which is a reasonable assumption as if the policy fails to load there is a good chance SELinux would block access to /dev/console). I had a quite glance through dinit-log.cc and it appears like it just uses stdout - would this be correct?

I'm not a fan of the re-exec approach either. If the correct label can be assigned to the already-running executable (i.e. what systemd apparently does), it seems like we should just do that.

I'll make sure to change that to use setcon_raw(3)

I'm inclined to think that there should either be a command-line option to disable loading the policy, or that should be the default and there should a command-line option to enable it.

Generally the command-line option is provided to the kernel cmdline (which the selinux_init_load_policy parses and handles for us). The main options are enforcing=0 (force SELinux to boot in enforcing mode regardless of /etc/selinux/config) and selinux=0 (disable selinux alltogether). So as far as I can tell, all of that should be handled for us

Probably the whole setup should be moved to its own separate function

I'll make sure to do that

@WavyEbuilder
Copy link
Author

Also, would you like me to commit any changes as separate commits until you are happy with it so you can see the diffs between changes a bit easier, or would rebasing be preferred?

@WavyEbuilder
Copy link
Author

Alright took a look at this a bit more thoroughly and I have a few design questions to raise quickly, notably regarding Probably the whole setup should be moved to its own separate function:

  1. Shall we plan ahead now for other security frameworks? I'm only really an SELinux guy as I mentioned in Load security policies for LSMs #399 , but it might be worth doing similar to systemd, i.e.:
static int initialize_security(
                bool *loaded_policy,
                dual_timestamp *security_start_timestamp,
                dual_timestamp *security_finish_timestamp,
                const char **ret_error_message);

Then we could just call our implementation of a similar function once in dinit_main (ideally as early as possible, being security frameworks it makes sense to attempt to load them as early as possible). Now given that we have C++ to hand here, I was wondering how to go about propagating errors back. Being C++11, we don't have anything like std::optional, but taking a look at some functions that can return failure in dinit's source, they appear to return a bool. My original idea was something like std::optional<std::string> (and returning an error message on failure, otherwise std::nullopt), but of course that is only available in C++17. Would something like char * work here instead then maybe (returning nullptr on success... though that's a bit strange granted)? Or is the specific failure message relevant at all here and should we just return a bool to indicate success status?

  1. Regarding headers for this, I was thinking maybe something along the lines of:
    src/includes/mac-util.h // contains initialize_security, might be worth just putting it in dinit-util.h?
    src/includes/dinit-mac/selinux.h // SELinux helper functions so we could (like systemd again) just quickly call a generic setup function for each MAC framework.

I think that'd be a reasonable way of structuring things, but being my first PR to dinit and my first real work on a C++ project below 14, your input would be greatly appreciated.

Thanks!

@davmac314
Copy link
Owner

taking a look at some functions that can return failure in dinit's source, they appear to return a bool ... Would something like char * work here instead then maybe (returning nullptr on success... though that's a bit strange granted)? Or is the specific failure message relevant at all here and should we just return a bool to indicate success status?

Log any relevant message (via log(...) functions), then return a bool (usually false for failure).

Shall we plan ahead now for other security frameworks?

If we're just talking about adding a single method, I don't see any advantage in doing that now, as it can easily be done if and when support for other security frameworks are added. Let's just keep it simple.

Generally the command-line option is provided to the kernel cmdline (which the selinux_init_load_policy parses and handles for us). The main options are enforcing=0 (force SELinux to boot in enforcing mode regardless of /etc/selinux/config) and selinux=0 (disable selinux alltogether). So as far as I can tell, all of that should be handled for us

Ok, that sounds fine.

@davmac314
Copy link
Owner

Generally the command-line option is provided to the kernel cmdline (which the selinux_init_load_policy parses and handles for us). The main options are

Actually, thinking about this more, there may still be cases where SELinux is enabled but the loading of the policy should not be performed. One example is given by the Systemd code here.

Also, can you clarify what this might mean? I want to know what file descriptors SELinux would keep open and in what circumstances.

Are you doing this work for a distribution or is it a more personal endeavour?

@davmac314
Copy link
Owner

(Finally: make sure you have read CONTRIBUTING and CODE-STYLE documents, if you haven't already. Thanks!).

@WavyEbuilder
Copy link
Author

WavyEbuilder commented Oct 17, 2024

Log any relevant message (via log(...) functions), then return a bool (usually false for failure).

Got it, thanks :)

If we're just talking about adding a single method, I don't see any advantage in doing that now, as it can easily be done if and when support for other security frameworks are added. Let's just keep it simple.

Yup, makes sense, should be fairly easy with to deal in the future. Will do!

Actually, thinking about this more, there may still be cases where SELinux is enabled but the loading of the policy should not be performed. One example is given by the Systemd code here.

That's a good example. For that specific initrd case, I had a look at systemd's in_initrd(void) function and found this comment:

/* If /etc/initrd-release exists, we're in an initrd.
 * This can be overridden by setting SYSTEMD_IN_INITRD=0|1.
 */ 

Would you like to do the same with an override here? (maybe something more like DINIT_IN_INITRD)

If you'd still like to add a flag override of some sorts to tell dinit to not load the selinux policy, I feel like that should be an opt in sort of thing, because while not loading the selinux policy won't load any of the user's policy, it doesn't mean selinux won't be loaded. In that case, everything runs in the kernel context, and taking my distro (Gentoo) as an example, Portage fails to operate if I just run with the system booted in the kernel context, so that is very much an edge case and almost never intended to be a reality. But the initrd case makes sense.

Also, can you clarify what this might mean? I want to know what file descriptors SELinux would keep open and in what circumstances.

Afaik this is generally in the case of when it needs to audit something related to that fd so it keeps it open for a bit? I remember seeing something similar in the past, but I'm not exactly too happy with that answer as I can't answer it with 100% confidence, so if that's okay I'll do a bit of digging in the libselinux docs and get back to you on that.

Are you doing this work for a distribution or is it a more personal endeavour?

I'm currently using Gentoo and dinit on basically all of my systems (which doesn't have upstream Gentoo support currently), however I am hoping to try improving the support (and maybe possibly getting official support) for dinit for both Adelie and Gentoo (nothing offical, just me on my own there, though I have spoken to some developers of the respective distros about that, but absoloutly nothing really offical yet). This specific piece of work was started when I hit a few weird bugs with my SELinux policy while dealing with a few ebuilds for dinit related to SELinux (policy for it), so in the future as Gentoo has offical SELinux support it might be useful, but for now really just take it as a personal endeavour, I'm not affiliated with any distro officially :)

(Finally: make sure you have read CONTRIBUTING and CODE-STYLE documents, if you haven't already. Thanks!).

Had a read over them already, but I'll make sure to reread CODE-STYLE

@WavyEbuilder
Copy link
Author

Did a bit of digging and found this commit systemd/systemd@a3dff21 which seems to explain it quite nicely.

@WavyEbuilder
Copy link
Author

Hmm reading the setcon(3) man page:

sets  the  current  security context of the process to a new value.  Note that use of this function requires that the entire application be trusted to maintain any desired separation between the old and new security contexts, unlike exec-based transitions performed via setexeccon(3).  When possible, decompose your application and use setexeccon(3) and execve(3) instead.

Still seems fine to transition with setcon_raw(3), but it probably makes sense to make sure to do it as early as possible, before we open any other file descriptors. I'll push a new commit using setcon_raw(3) shortly.

@WavyEbuilder
Copy link
Author

I think it'll be best to consider how SELinux aware we want dinit to be at this stage. After reading some more man pages and systemd code, it seems like systemd transitioning itself to the new context is an okay option as they already make heavy use of selinux throughout (i.e. in transient units which have an SELinuxContext= option). However, if our only goal (at least in the short-term) is to load the policy, then I think it makes sense to stick with the execve(3) solution.

If we want to be a little bit more SELinux aware, (i.e. if it is not unforeseeable to make use of libselinux more throughout dinit), then I would probably start off by creating an selinux utils header of some point as there is quite a bit of setup, etc that'll need to be done.

My personal opinion would be (for the sake of simplicity) to stick with the execve(3) solution as it'd be a fair amount simpler for now. In the future, if something like the dinit-run and transient units mentioned in #253 (comment) gets implemented, we could add support for launching said units with a specific selinux context (I'd be happy to work on something like that), and at that point as that'd require a decent amount of setup anyway, it'd make sense to just use setcon_raw(3) at that point. I'm guessing the (relatively) unneeded complexity of correctly transitioning ourself to the right domain after loading the policy is why the other simpler init systems (openrc, sysvinit, etc) that don't really make use of a lot of SELinux's features just load the policy and relaunch themselves.

However, if you'd still like to continue with setting our own context, I can go down that route. It'd require a bit more design though, so it might be worth working on getting some helper functions stubbed out firstly.

@davmac314
Copy link
Owner

for now really just take it as a personal endeavour, I'm not affiliated with any distro officially :)

That's fine but it will need a commitment from you that you will support it going forward, or otherwise make it clear that it's experimental/unsupported in relevant documentation. (Incidentally I think you missed updating the build instructions - that's something that would need to be added).

To be honest I'm not sure I'm following your reasoning in a few ways:

it seems like systemd transitioning itself to the new context is an okay option as they already make heavy use of selinux throughout (i.e. in transient units which have an SELinuxContext= option)

I don't really understand why that makes a difference. What is the reason why this would not be a good option for dinit as well? (I get that Dinit doesn't provide specific support for SELinux features when executing service processes, but why does that make a difference as to the mechanics of how the policy is loaded?)

I'm fine with the policy loading happening very early in dinit's execution. But:

My personal opinion would be (for the sake of simplicity) to stick with the execve(3) solution

If we are going to call execve anyway, I'm not sure I see any point having the functionality in dinit itself. It could just as well be a wrapper (called init) that loads the policy and then execves dinit. Or am I missing something? Having dinit re-exec itself on each boot doesn't seem right to me at all.

I know you had a few other questions for me and I can go back to those, but I really need some clarification on these points. I don't want to be discouraging but it seems like there are a few details you're not really sure of yourself, and that gives me some pause. I'm hesitant to incorporate something where I really don't understand why things have been done the way they have. If there's open questions that you need to sort out, please feel free to take whatever time you need to do that, but let's get them sorted first and talk details of the code then.

@WavyEbuilder
Copy link
Author

Hey,

That's fine but it will need a commitment from you that you will support it going forward, or otherwise make it clear that it's experimental/unsupported in relevant documentation. (Incidentally I think you missed updating the build instructions - that's something that would need to be added).

I can commit to that, but would also be happy mentioning it is experimental.

I don't really understand why that makes a difference. What is the reason why this would not be a good option for dinit as well? (I get that Dinit doesn't provide specific support for SELinux features when executing service processes, but why does that make a difference as to the mechanics of how the policy is loaded?)

I think I phrased that badly earlier, I'll rephrase it a little here now. Systemd makes use of SELinux a lot inside it being quite SELinux aware so it already has a lot of boilerplate that will be used elsewhere. The reason why transitioning to the new context is a little more complex is because it requires a bit more setup, we are in a privileged domain at that point and we are sort of entrusting ourselves to do it right, so it'd require a fair amount more code I would think.

If we are going to call execve anyway, I'm not sure I see any point having the functionality in dinit itself. It could just as well be a wrapper (called init) that loads the policy and then execves dinit. Or am I missing something? Having dinit re-exec itself on each boot doesn't seem right to me at all.

An initramfs can work fine for this (and often is!) or some simpler pid 1 that's only job is to launch dinit properly with the right context, but (at least to me) that feels a little unnecessary.

I know you had a few other questions for me and I can go back to those, but I really need some clarification on these points. I don't want to be discouraging but it seems like there are a few details you're not really sure of yourself, and that gives me some pause.

That's fair, I did phrase it quite badly above. My main reasoning was based off the Let's just keep it simple. comment, so basically the only "problem" is that it's just a bit more work that we need to get right for (at least in my opinion) minimal gain. However there's nothing preventing us from doing that if you wish :) It's just a bit more code, so I thought I'd mention that.

I'm hesitant to incorporate something where I really don't understand why things have been done the way they have. If there's open questions that you need to sort out, please feel free to take whatever time you need to do that, but let's get them sorted first and talk details of the code then.

That makes sense. For now I'll just presume we're going down the route of transitioning ourselves to a new context and I'll push in a bit with an example of that and let you compare.

Incidentally I think you missed updating the build instructions - that's something that would need to be added).
I did miss that, my bad, I'll make sure to update that as well.

@davmac314
Copy link
Owner

davmac314 commented Oct 17, 2024

I think I phrased that badly earlier, I'll rephrase it a little here now. Systemd makes use of SELinux a lot inside it being quite SELinux aware so it already has a lot of boilerplate that will be used elsewhere. The reason why transitioning to the new context is a little more complex is because it requires a bit more setup, we are in a privileged domain at that point and we are sort of entrusting ourselves to do it right, so it'd require a fair amount more code I would think.

This, I guess, is what I don't understand. I can see that opening file descriptors before loading the policy might give access to things that the policy will then disallow but, if we are loading the policy quite early and we have opened file descriptors then in fact we do need those file descriptors. If the policy disallowed that access then that would be a broken policy anyway. Dinit doesn't go around just casually opening files. Likewise any other resource it has accessed, it probably needs. And anyway, as far as I can tell, applying the security label will enforce access against file descriptors that were opened previously anyway.

Eg from https://www.systutorials.com/docs/linux/man/3-setcon_raw/ -

Since access to file descriptors is revalidated upon use by SELinux, the new context must be explicitly authorized in the policy to use the descriptors opened by the old context if that is desired.

If the process was being ptraced at the time of the setcon() operation, ptrace permission will be revalidated against the new context and the setcon() will fail if it is not allowed by policy.

Given those are taken care of (and ptrace shouldn't be an issue anyway), and given that we'd be loading the policy early (before doing just about anything anyway), what would be the concerns in regards to "entrusting ourselves to do it right?" I'm after concrete examples.

An initramfs can work fine for this (and often is!) or some simpler pid 1 that's only job is to launch dinit properly with the right context, but (at least to me) that feels a little unnecessary.

To me it feels unnecessary to me add specific support (including a library dependency) for something in Dinit which can be handled just as well from outside, and re-executing our own process right after we start honestly just feels like a hack. At the moment my position on that is a "no", I would need to be given a good, concrete reason for why that should change.

Applying the security context within the already-running process without re-execing would be acceptable, though.

My main reasoning was based off the Let's just keep it simple. comment, so basically [...] It's just a bit more code, so I thought I'd mention that.

A little bit more code isn't an issue, if we have already gone as far as adding a dependency and providing support for SELinux then we may as well do it properly. My bad for the "keep it simple" comment which caused confusion - I meant, keep it restricted to the specific functionality that you are wanting to implement; we don't need abstraction layers for handling other security frameworks, etc.

But before you said:

so it'd require a fair amount more code I would think.

Is it a bit, or is it a fair amount? (or am I conflating two different things?)
(Edit: what I'm really asking is: is it a matter of say 3-4x the amount of code currently in the PR, all confined to a single function? Or are we talking sweeping changes throughout the codebase? If it's the former, that's totally fine).

@WavyEbuilder
Copy link
Author

WavyEbuilder commented Oct 18, 2024

As for entrusting ourselves to do it right, the main concern surrounds file descriptors. That is why I'm a little worried about the log interface. We don't want to leave any of our file descriptors open when we transition. Then in effect we would have a "context mismatch" otherwise, as the file descriptor inherits the context of the process it was opened by. So we would have issues regarding access control to existing contexts at that point . That's ideally why I'm thinking we load ourselves as early as possible. If we do that, we should be fine.

A good example is this. Imagine we start out with kernel context (what dinit starts out with on my system before the policy is loaded). We have some fd's opened, and the kernel context has permission to use them. Now we load the policy, transition ourselves, and the loaded policy executes us as init_t. In the Gentoo refpolicy, then that kernel context becomes kernel_t. Now SELinux will prevent us from using those open file descriptors.

(Edit: what I'm really asking is: is it a matter of say 3-4x the amount of code currently in the PR, all confined to a single function? Or are we talking sweeping changes throughout the codebase? If it's the former, that's totally fine).

Oh I see what you meant by keeping it simple now :) I was a bit confused with what you were after, but it shouldn't really require any sweeping changes for the codebase, it should all be confined to that function we'll make to load the policy, which will be the thing that's a bit longer. That's all good then, I can make the transition work.

I'll get to work on that, and if there are any concerns please let me know. Thanks for all the time you've given this so far, appreciated a lot.

@WavyEbuilder WavyEbuilder force-pushed the master branch 2 times, most recently from 5ddfc4d to d5295d9 Compare October 18, 2024 04:01
@WavyEbuilder
Copy link
Author

Alright I think I've got this working as desired now. I've just made a function selinux_transition that is above dinit_main for now so you can take a look, if you'd like me to move it let me know.

If anything is unclear/you feel any comments are needed, please let me know, and I'll make sure to add them.

@WavyEbuilder
Copy link
Author

(just updated an error message as i'm not longer using setexeccon_raw(3) and removed a close as i am no longer opening something else). Should be ready for review now

@WavyEbuilder
Copy link
Author

Just fixed another silly mistake, forgot to chance 0 and 1 to true and false as I changed the return type to a bool as you suggested. My apologies, actually ready for review now.

It's misleading to say that a policy choice is a misconfiguration, the
choice to prevent dinit from transitioning from its inital domain is a
choice made the local system administrator. Let's clarify our comments
to specify that this isn't an error, but a warning, as this is still a
unsual policy choice.
@WavyEbuilder
Copy link
Author

Hi Davin,

Just thought I'd give a small update as it's been quite a while now.

The current mechanism so far seems robust, however:

  • man pages need additional selinux-related documentation as you requested
  • I've tested the main selinux_transition mechanism quite a bit, I'm fairly happy with it, but I still want to test a few more edge cases
  • I need to mount /proc in selinux_transition and unmount afterwards (and this also needs documenting as you mentioned). Reasoning for this is because systems without an initramfs will have nothing to mount /proc and as the load policy function unmount /proc after it is done with it, we need to mount it ourselves (and possibly unmount afterwards, need to research if that'd make sense and why the selinux load policy function does so).

I'll be less active over Christmas so it'll be a few weeks before I push anything more, but I'll clean up the merge conflicts as well next. Just wanted to note that I haven't abandoned the PR.

Thanks

@davmac314
Copy link
Owner

Hi, that's fine, but I have one major concern after just having looked over the current changes.

There is some code that is currently part of the PR:

    // getcon_raw(3) can return 0, and still give us a NULL pointer if /proc/self/attr/current is
    // empty. SELinux guarentees this won't happen, but other LSMs may edit or control that file.
    // It's best to check the pointer in addition to the return value.
    if (getcon_raw(&current_context) < 0 || current_context == nullptr) {
        cerr << "Failed to get current context: " << strerror(errno) << endl;
        goto cleanup;
    }

Compared to some code that you pasted earlier, which turns out to be from Systemd:

        r = getcon_raw(&con);
        /* getcon_raw can return 0, and still give us a NULL pointer if /proc/self/attr/current is
         * empty. SELinux guarantees this won't happen, but that file isn't specific to SELinux, and may be
         * provided by some other arbitrary LSM with different semantics. */
        if (r == 0 && con) {
                initialized = !streq(con, "kernel");
                freecon(con);
        } else
                initialized = false;

Obviously they are not completely identical, but just as obviously, at least the comment was taken from Systemd and then modified slightly for this PR.

You cannot do that. All code and comments in the PR should be your own work (and if any isn't, this absolutely needs to be flagged when you raise the PR). This is true not just for Dinit but any project where you open a PR.

The Systemd license is not compatible with the Dinit license, and we do not have the right to relicense code that is derived from Systemd code.

I know this is only a small piece of code (assuming there is not more that is copied) but this is a major issue. This could cause massive headaches down the line if a Systemd developer discovered that code, and realised where it originated from. They might insist that the code be removed, or in the worst case I could end up in some legal entanglement.

You will need to re-do any code that you copied from Systemd or anywhere else. I'm afraid you will need to find your own wording for the comments. It is honestly better to not even look at the Systemd code. And since this has come up, I'm going to have to get you to confirm again once this is ready whether the PR is your own work.

@WavyEbuilder
Copy link
Author

Thanks for the heads up - I didn't think that'd be copyrightable/was fairly trivial, got it now and noted for the future.

I gave a cursory glance over at the changes so far, everything outside of dinit.cc seems completely fine to me. Looking at dinit.cc:
https://github.com/davmac314/dinit/pull/400/files#diff-478d55d4071495e39c6c94175bef40d012ddcbcd6c35fb57766263e2cf690bfdR476-R491
I didn't really base that off anything except for the template for function comments you gave in CODE-STYLE as far as I remember so that seems completely fine to me.

https://github.com/davmac314/dinit/pull/400/files#diff-478d55d4071495e39c6c94175bef40d012ddcbcd6c35fb57766263e2cf690bfdR493-R495
This is C++ so original

https://github.com/davmac314/dinit/pull/400/files#diff-478d55d4071495e39c6c94175bef40d012ddcbcd6c35fb57766263e2cf690bfdR514-R518
https://github.com/davmac314/dinit/pull/400/files#diff-478d55d4071495e39c6c94175bef40d012ddcbcd6c35fb57766263e2cf690bfdR544-R546
These were discovered by testing not reading anything, so also should be original

https://github.com/davmac314/dinit/pull/400/files#diff-478d55d4071495e39c6c94175bef40d012ddcbcd6c35fb57766263e2cf690bfdR594-R601
This was also written by me, with the error exit part copied from down below in the dinit.cc file so should be good

Everything else there should be good as far as I can tell, I'll make sure to give it a look through again later.

I know this is only a small piece of code (assuming there is not more that is copied) but this is a major issue. This could cause massive headaches down the line if a Systemd developer discovered that code, and realised where it originated from. They might insist that the code be removed, or in the worst case I could end up in some legal entanglement.

I understand, all good.

You will need to re-do any code that you copied from Systemd or anywhere else. I'm afraid you will need to find your own wording for the comments.

I'll make sure to do that. Appears to just be that snippet

It is honestly better to not even look at the Systemd code.

Noted for anything else I write.

And since this has come up, I'm going to have to get you to confirm again once this is ready whether the PR is your own work.

All good. So far I think everything else looks fine, I'll recheck again later as well.

@davmac314
Copy link
Owner

davmac314 commented Dec 17, 2024

Ok, thanks, I appreciate you taking this seriously.

I didn't think that'd be copyrightable/was fairly trivial, got it now and noted for the future

While it is only a small piece of code, that doesn't mean it's not copyrightable. I'm not a lawyer so I don't claim to know for sure whether copyright would apply to the comment but I suspect it would (and I don't want to take the risk anyway).

But also, if any code is based off someone else's work even in a small way, that should always be acknowledged (eg in a comment) - regardless of copyright, it's the right thing to do.

In this case I'd rather simply not have either issue, i.e. have the code written from scratch.

Change up the wording to avoid ethical and licensing headache with
systemd.
@WavyEbuilder
Copy link
Author

WavyEbuilder commented Dec 18, 2024

Hi Davin,

Could I ask you to review the latest commit? I'm not really familiar with the ins and outs of copyright, and I'm unsure as to whether or not that commit addresses the issue.

From your previous comment:

You will need to re-do any code that you copied from Systemd or anywhere else. I'm afraid you will need to find your own wording for the comments

I have reworded the comment (let me know if that isn't reworded suitably), but I don't think the actual check made in this commit e06e054#diff-478d55d4071495e39c6c94175bef40d012ddcbcd6c35fb57766263e2cf690bfdR519 (the code, not the comment) is copyrightable as it is simply logic and not really related to systemd code at all.

For clarity, I'm referring to && current_context == nullptr as the change that is not a concern.

Thanks

@WavyEbuilder
Copy link
Author

WavyEbuilder commented Dec 18, 2024

I've decided it might just be best to do a cleanroom rewrite of that comment instead, so I did so in a blank text editor. For full transparency, it's based off the wording of the getcon(3) manpage which has this quote under the NOTES section:

The retrieval functions might return success and set *context to NULL if and only if SELinux is not enabled.

This is located in the source of libselinux here: https://github.com/SELinuxProject/selinux/blob/main/libselinux/man/man3/getcon.3#L147-L150

Looking at the license of libselinux: https://github.com/SELinuxProject/selinux/blob/main/libselinux/LICENSE

It appears to be public domain software, which as far as I can tell means it should be okay to quote. I deemed that a comment giving acknowledgement to the NSA or the SELinux Project was unnecessary for this, as it is the manpage of the function I'm calling. However, let me know if you'd like me to add one, I'd be more than happy to do so

@davmac314
Copy link
Owner

I think you need to use your judgement (taking in to account what I've already said). These things aren't always black and white and I don't really want to be pulled in to make a judgement on every thing that comes up. Please get the PR to the state where you are satisfied with it and ask for review only at that stage (remember to self-review first).

Quick couple of points now since I have been drawn in to look at it:

  • Does *context come specifically from the man page? Then as I said earlier you would need to acknowledge the origin, and that acknowledgement is currently missing.
  • The *context in the comment isn't actually very clear since that doesn't appear in the code. That's a separate issue though.

Once again, please complete the PR before asking for review.

@davmac314
Copy link
Owner

Btw:

It appears to be public domain software, which as far as I can tell means it should be okay to quote. I deemed that a comment giving acknowledgement to the NSA or the SELinux Project was unnecessary for this, as it is the manpage of the function I'm calling

Quoting would certainly be fine (even verbatim) and in that case then it is absolutely a good idea to say where the quote comes from. What I said before was:

if any code is based off someone else's work even in a small way, that should always be acknowledged

That does not say that necessarily "you must acknowledge the specific authors of the work", but rather "you must acknowledge that the code is based off someone else's work". Something like "as stated in the man page for ..." would do that. I think if you are quoting info from a man page then acknowledging that is not only a good thing to do, it is genuinely useful.

@WavyEbuilder
Copy link
Author

Thanks for all your clarifications, I appreciate it. Just wanted to err on the side of caution as (understandably) copyright is a sensitive topic. Think I've got it now.

I'll continue on with the PR with self-review until it is ready for review (i.e. mergeable should no other issues come up).

TODO: document mounting of /proc. This is intentionally missing for now
until dinit's behaviour regarding the mounting of /proc directly itself
for selinux_transition is decided.

Signed-off-by: Rahul Sandhu <[email protected]>
Note: unfinished

Signed-off-by: Rahul Sandhu <[email protected]>
There is little need to use type inference for errno_str; just use char
* for clarity

Signed-off-by: Rahul Sandhu <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Importance: Normal C-dinit Things about the main parts of dinit Enhancement/New Feature Improving things or introduce new feature make Things about Dinit's Make build system meson Things about Dinit's Meson build system P-Linux Things related to Linux
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants