target rootfs permissions
Hi all,
I've noticed that when building a rootfs, some of the permissions on the target depend on the users umask (directly and indirectly). This occurs because some files (notably the system skeleton and overlay) are copied with "rsync -a", which copies permissions exactly as they were on the source. The thing is, Git doesn't track file permissions (except for the exec bit) so both of these depend on the users umask at the time of cloning (if there were no posterior changes).
Also, some files are created in BR code with cp/mkdir, which depend on the current umask.
I think this is pretty important, since if we do care about permissions, the target rootfs may not be easily reproducible on other hosts.
For my current project, we do need a specific set of permissions and ownerships for each file in the rootfs. We're trying to isolate the custom application from the rest of the system, and give it the exact privileges it needs. I found that when I build the rootfs (my umask was 0027) the application could not do absolutely anything as / wasn't executable or readable by it. But building on other hosts (with more relaxed umasks) we had a working rootfs.
We accomplished this by adding a custom script that gets called just prior to the image creation, inside of the fakeroot script (thus, it gets called multiple times, but this isn't a big deal for us).
One downside of our approach is that in order to not depend on the previous set of permissions (which could vary), we need to specify the exact mode for each file. So we need to set the sticky bit on /tmp manually, make /etc/shadow not readable and etc, etc, etc.
Permissions alone could (maybe) be fixed by changing BR code to be aware of this issue, and by setting correct permissions on the overlay/skeleton via some script. But ownerships cannot be changed by a non-root user! And, since building as root is a Very Bad Thing (tm), we'd need to resort to fakeroot.
So: has anyone else had this problem?
Is it important for someone else?
What do you think a mainline solution would look like?
Thanks a lot guys!
Signature · 2 lines
Guido Mart?nez, VanguardiaSur www.vanguardiasur.com.ar
Dear Guido Mart?nez,
Quoted 37 lines · Guido Mart?nez
I've noticed that when building a rootfs, some of the permissions on the target depend on the users umask (directly and indirectly). This occurs because some files (notably the system skeleton and overlay) are copied with "rsync -a", which copies permissions exactly as they were on the source. The thing is, Git doesn't track file permissions (except for the exec bit) so both of these depend on the users umask at the time of cloning (if there were no posterior changes).
Also, some files are created in BR code with cp/mkdir, which depend on the current umask.
I think this is pretty important, since if we do care about permissions, the target rootfs may not be easily reproducible on other hosts.
For my current project, we do need a specific set of permissions and ownerships for each file in the rootfs. We're trying to isolate the custom application from the rest of the system, and give it the exact privileges it needs. I found that when I build the rootfs (my umask was 0027) the application could not do absolutely anything as / wasn't executable or readable by it. But building on other hosts (with more relaxed umasks) we had a working rootfs.
We accomplished this by adding a custom script that gets called just prior to the image creation, inside of the fakeroot script (thus, it gets called multiple times, but this isn't a big deal for us).
One downside of our approach is that in order to not depend on the previous set of permissions (which could vary), we need to specify the exact mode for each file. So we need to set the sticky bit on /tmp manually, make
/etc/shadownot readable and etc, etc, etc.Permissions alone could (maybe) be fixed by changing BR code to be aware of this issue, and by setting correct permissions on the overlay/skeleton via some script. But ownerships cannot be changed by a non-root user! And, since building as root is a Very Bad Thing (tm), we'd need to resort to fakeroot.
Quoted 3 lines
So: has anyone else had this problem?
Is it important for someone else?
What do you think a mainline solution would look like?
Thanks for your report. It is indeed a problem that should be fixed. The only clean solution that I see is to have the fakeroot script reset the permission for all files to a certain sane value (just like we already have a 'chown -h -R 0:0' to re-assign all files to the root user), and then re-adjust using makedevs the permissions of the needed files, such as /tmp, /etc/shadow and so on.
Since /tmp, /etc/shadow and so on are part of the skeleton, one option would be to make the skeleton a real package, so it could declare a SKELETON_PERMISSIONS variable to adjust whatever is needed. This is quite in line with some discussions we had recently about cleaning up the skeleton from init scripts, and possibly making it a proper package.
I'm Cc'ing Maxime and Gustavo, who are both active on this topic.
Best regards,
Thomas
Signature · 3 lines
Thomas Petazzoni, CTO, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com
Hi all,
Quoted 45 lines · Thomas Petazzoni
Dear Guido Mart?nez,
Quoted 37 lines · Guido Mart?nez
I've noticed that when building a rootfs, some of the permissions on the target depend on the users umask (directly and indirectly). This occurs because some files (notably the system skeleton and overlay) are copied with "rsync -a", which copies permissions exactly as they were on the source. The thing is, Git doesn't track file permissions (except for the exec bit) so both of these depend on the users umask at the time of cloning (if there were no posterior changes).
Also, some files are created in BR code with cp/mkdir, which depend on the current umask.
I think this is pretty important, since if we do care about permissions, the target rootfs may not be easily reproducible on other hosts.
For my current project, we do need a specific set of permissions and ownerships for each file in the rootfs. We're trying to isolate the custom application from the rest of the system, and give it the exact privileges it needs. I found that when I build the rootfs (my umask was 0027) the application could not do absolutely anything as / wasn't executable or readable by it. But building on other hosts (with more relaxed umasks) we had a working rootfs.
We accomplished this by adding a custom script that gets called just prior to the image creation, inside of the fakeroot script (thus, it gets called multiple times, but this isn't a big deal for us).
One downside of our approach is that in order to not depend on the previous set of permissions (which could vary), we need to specify the exact mode for each file. So we need to set the sticky bit on /tmp manually, make
/etc/shadownot readable and etc, etc, etc.Permissions alone could (maybe) be fixed by changing BR code to be aware of this issue, and by setting correct permissions on the overlay/skeleton via some script. But ownerships cannot be changed by a non-root user! And, since building as root is a Very Bad Thing (tm), we'd need to resort to fakeroot.
Quoted 3 lines
So: has anyone else had this problem?
Is it important for someone else?
What do you think a mainline solution would look like?
Quoted 6 lines
Thanks for your report. It is indeed a problem that should be fixed. The only clean solution that I see is to have the fakeroot script reset the permission for all files to a certain sane value (just like we already have a 'chown -h -R 0:0' to re-assign all files to the root user), and then re-adjust using makedevs the permissions of the needed files, such as /tmp,
/etc/shadowand so on.
Good to know I'm not crazy! ;)
I have been trying a solution based on running 'chmod -R u=rwX,go=rX' for the last few days and it seems to work just fine. We're basically making everything public (exception should go in the device table or in *_PERMISSIONS) and keeping the executable bits of files that already have them. This saves the trouble of making packages declare which files should be executable.
Packages should only declare ownerships, special permissions (like sticky bits and setuids) and private files (like /etc/sudoers). Most of them (at least the ones I could find) do exactly this, so I don't think much breakage should appear (but undoubtedly, some will). I'd go as far as saying that 644 is the default permissions everyone unconsciously has in mind.
A build using this change is perfectly reproducible, given one does not mess with output/target too much (if you set the exec bit on a random file, it will set).
This change also clears up quite a bit of system/device_table.txt since most of the permissions declared there are the defaults.
I can submit a proper patch if it sounds reasonable for you guys.
Quoted 5 lines
Since /tmp,
/etc/shadowand so on are part of the skeleton, one option would be to make the skeleton a real package, so it could declare aSKELETON_PERMISSIONSvariable to adjust whatever is needed. This is quite in line with some discussions we had recently about cleaning up the skeleton from init scripts, and possibly making it a proper package.
Right, that would be great, but it wouldn't fix the issue of variability due to the permissions of the overlay files (hence due to the umask too), right?
Cheers!
Signature · 2 lines
Guido Mart?nez, VanguardiaSur www.vanguardiasur.com.ar
Quoted 14 lines · Guido Mart?nez
Hi all,
Quoted 11 lines · Thomas Petazzoni
Dear Guido Mart?nez,
Quoted 7 lines · Guido Mart?nez
I've noticed that when building a rootfs, some of the permissions on the target depend on the users umask (directly and indirectly). This occurs because some files (notably the system skeleton and overlay) are copied with "rsync -a", which copies permissions exactly as they were on the source. The thing is, Git doesn't track file permissions (except for the exec bit) so both of these depend on the users umask at the time of cloning (if there were no posterior changes).
[snip]
Quoted 15 lines
Quoted 6 lines
Thanks for your report. It is indeed a problem that should be fixed. The only clean solution that I see is to have the fakeroot script reset the permission for all files to a certain sane value (just like we already have a 'chown -h -R 0:0' to re-assign all files to the root user), and then re-adjust using makedevs the permissions of the needed files, such as /tmp,
/etc/shadowand so on.Good to know I'm not crazy! ;)
I have been trying a solution based on running 'chmod -R u=rwX,go=rX' for the last few days and it seems to work just fine. We're basically making everything public (exception should go in the device table or in
*_PERMISSIONS) and keeping the executable bits of files that already have them. This saves the trouble of making packages declare which files should be executable.
Quoted 6 lines
Packages should only declare ownerships, special permissions (like sticky bits and setuids) and private files (like
/etc/sudoers). Most of them (at least the ones I could find) do exactly this, so I don't think much breakage should appear (but undoubtedly, some will). I'd go as far as saying that 644 is the default permissions everyone unconsciously has in mind.
There is one problem with this solution: it means that for each package, we
have to make sure that we find and apply all the special permissions it requires. And that's something that can only be discovered at runtime. It's much better if we could rely on the package's build infrastructure to do the right thing.
So what we really want to do is to clear the umask. I found [1] which suggests
to do
SHELL = /bin/bash --noprofile -c 'umask 000; eval "$$2"' --
Alternatively, we could also reset the umask in the places where it's relevant,
i.e. where rsync and cp are used - but that's a bit complicated an risky - we might forget something.
For the skeleton and overlay, the umask is not the issue, it's just the fact
that we preserve permissions. That could easily be solved by using --chmod=u=rwX,go=rX for rsync.
Regards,
Arnout
[1] http://lists.gnu.org/archive/html/bug-gnu-utils/2012-03/msg00012.html
Quoted 20 lines
A build using this change is perfectly reproducible, given one does not mess with output/target too much (if you set the exec bit on a random file, it will set).
This change also clears up quite a bit of
system/device_table.txtsince most of the permissions declared there are the defaults.I can submit a proper patch if it sounds reasonable for you guys.
Quoted 5 lines
Since /tmp,
/etc/shadowand so on are part of the skeleton, one option would be to make the skeleton a real package, so it could declare aSKELETON_PERMISSIONSvariable to adjust whatever is needed. This is quite in line with some discussions we had recently about cleaning up the skeleton from init scripts, and possibly making it a proper package.Right, that would be great, but it wouldn't fix the issue of variability due to the permissions of the overlay files (hence due to the umask too), right?
Cheers!
Signature · 6 lines
Arnout Vandecappelle arnout at mind be Senior Embedded Software Architect +32-16-286500 Essensium/Mind http://www.mind.be G.Geenslaan 9, 3001 Leuven, Belgium BE 872 984 063 RPR Leuven LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle GPG fingerprint: 7CB5 E4CC 6C2E EFD4 6E3D A754 F963 ECAB 2450 2F1F
Hey Arnout,
Quoted 16 lines · Arnout Vandecappelle
On 30/10/14 14:15, Guido Mart?nez wrote:
[snip]Quoted 7 lines
I have been trying a solution based on running 'chmod -R u=rwX,go=rX' for the last few days and it seems to work just fine. We're basically making everything public (exception should go in the device table or in
*_PERMISSIONS) and keeping the executable bits of files that already have them. This saves the trouble of making packages declare which files should be executable.Quoted 6 lines
Packages should only declare ownerships, special permissions (like sticky bits and setuids) and private files (like
/etc/sudoers). Most of them (at least the ones I could find) do exactly this, so I don't think much breakage should appear (but undoubtedly, some will). I'd go as far as saying that 644 is the default permissions everyone unconsciously has in mind.
Quoted 4 lines
There is one problem with this solution: it means that for each package, we
have to make sure that we find and apply all the special permissions it requires. And that's something that can only be discovered at runtime. It's much better if we could rely on the package's build infrastructure to do the right thing.
You're right. This is an excellent point, thank you!
Quoted 4 lines
So what we really want to do is to clear the umask. I found [1] which suggests
to doSHELL =
/bin/bash--noprofile -c 'umask 000; eval "$$2"' --
I agree with trying to fix the umask, but that snippet doesn't work for me, not even in simple makefiles. One alternative I found is creating a script under support/ that wraps all shell calls setting the umask first, and setting SHELL to it.
BTW: Using a umask of 000 doesn't work really well. Some packages (at least nginx and bzip2) install files using plain mkdir/cp, so the binaries end up world-writable. I suggest 022.
Quoted 7 lines
Alternatively, we could also reset the umask in the places where it's relevant,
i.e. where rsync and cp are used - but that's a bit complicated an risky - we might forget something.For the skeleton and overlay, the umask is not the issue, it's just the fact
that we preserve permissions. That could easily be solved by using --chmod=u=rwX,go=rX for rsync.
Sounds reasonable.
I have a patch for both of these (wrapping shell calls and rsyncing with --chmod). I'll send an RFC later.
Thanks a lot!
Signature · 2 lines
Guido Mart?nez, VanguardiaSur www.vanguardiasur.com.ar