Project `restricted` status not taken into account when checking `restricted.*` settings during update
Please confirm
- [x] I have searched existing issues to check if an issue already exists for the bug I encountered.
Distribution
ubuntu
Distribution version
24.04
Output of "snap list --all lxd core20 core22 core24 snapd"
N/A
Output of "lxc info" or system info if it fails
N/A
Issue description
The docs say:
To prevent the instances of a project from accessing security-sensitive features (such as container nesting or raw LXC configuration), set the restricted configuration option to true. You can then use the various restricted.* options to pick individual features that would normally be blocked by restricted and allow them, so they can be used by the instances of the project.
https://documentation.ubuntu.com/lxd/latest/reference/projects/#project-restrictions
So the restricted.* keys should not be enforced unless restricted=true.
However during project update specifically this is not the case.
Steps to reproduce
lxc project create footest
lxc project switch footest
lxc project set footest restricted.virtual-machines.lowlevel=block # Without setting `restricted=true`
lxc init ubuntu:24.04 v1 --vm -s default
# Device is allowed to use `io.threads` despite `restricted.virtual-machines.lowlevel=block` because `restricted!=true`
lxc config device add v1 foo disk source=/mnt path=/mnt io.threads=4 # io.threads not blocked because `restricted!=true`
# This error shouldn't happen because it is wrongly enforcing `restricted.devices.disk` when `restricted!=true`.
lxc project set footest restricted.virtual-machines.lowlevel=allow # Without setting `restricted=true`
Error: Conflict detected when changing "restricted.virtual-machines.lowlevel" in project "footest": Invalid device "foo" on virtual-machine "v1" of project "footest": Attaching disks not backed by a pool is forbidden
lxc config device remove v1 foo
lxc project set footest restricted.virtual-machines.lowlevel=allow restricted.devices.disk=block
# Device is allowed to use `io.threads` and unmanaged source despite `restricted.*` keys because `restricted!=true`
lxc config device add v1 foo disk source=/mnt path=/mnt io.threads=4
lxc project set footest restricted=true
# Device not allowed because `restricted.devices.disk=block` and `restricted=true`
lxc config device add v1 foo disk source=/mnt path=/mnt io.threads=4
Error: Failed checking if instance update allowed: Invalid device "foo" on virtual-machine "v1" of project "footest": Disk devices are forbidden
lxc project set footest restricted.virtual-machines.lowlevel=block restricted.devices.disk=allow
# Device not allowed because `restricted.virtual-machines.lowlevel=block` and `restricted=true`
lxc config device add v1 foo disk source=/mnt path=/mnt io.threads=4
Error: Failed checking if instance update allowed: Invalid device "foo" on virtual-machine "v1" of project "footest": Use of low-level "io.threads" disk option forbidden
The issue appears to be in AllowProjectUpdate() with the call to checkInstanceRestrictions() without checking if the project's new config has restricted=true in it:
https://github.com/canonical/lxd/blob/df0e0eb629558cafd2beaf7ce900fc7399148a5c/lxd/project/limits/permissions.go#L1113
Compared to the call to checkInstanceRestrictions() in checkRestrictionsAndAggregateLimits which has a conditional on if isRestricted:
https://github.com/canonical/lxd/blob/df0e0eb629558cafd2beaf7ce900fc7399148a5c/lxd/project/limits/permissions.go#L385-L390