From: Paul Moore <hidden> Date: 2012-12-05 20:25:56
Second draft of the LSM/SELinux fixes to the upcoming multiqueue TUN
functionality. This draft incorporates all the comments/decisions
from the first draft, notably the new LSM and SELinux hook for the
TUNSETQUEUE operation. Other LSMs do not provide TUN controls so they
are not affected.
Once we decide this is the right approach I'll push the associated
SELinux policy FLASK definitions upstream; for those who are interested
the SELinux policy diff in included in the description of patch 1/2.
I don't expect this to be the final patch, just a starting point for
further discussion so I didn't really do any testing, simply making
sure that it compiled cleanly.
---
Paul Moore (3):
tun: correctly report an error in tun_flow_init()
selinux: add the "create_queue" permission to the "tun_socket" class
tun: fix LSM/SELinux labeling of tun/tap devices
drivers/net/tun.c | 29 +++++++++++++----
include/linux/security.h | 59 +++++++++++++++++++++++++++--------
security/capability.c | 24 ++++++++++++--
security/security.c | 28 ++++++++++++++---
security/selinux/hooks.c | 50 +++++++++++++++++++++++-------
security/selinux/include/classmap.h | 2 +
security/selinux/include/objsec.h | 4 ++
7 files changed, 156 insertions(+), 40 deletions(-)
From: Paul Moore <hidden> Date: 2012-12-05 20:26:07
On error, the error code from tun_flow_init() is lost inside
tun_set_iff(), this patch fixes this by assigning the tun_flow_init()
error code to the "err" variable which is returned by
the tun_flow_init() function on error.
Signed-off-by: Paul Moore <redacted>
---
drivers/net/tun.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
From: Paul Moore <hidden> Date: 2012-12-05 20:26:15
Add a new permission to align with the new TUN multiqueue support,
"tun_socket:create_queue".
The corresponding SELinux reference policy patch is show below:
diff --git a/policy/flask/access_vectors b/policy/flask/access_vectors
index 28802c5..a0664a1 100644
--- a/policy/flask/access_vectors
+++ b/policy/flask/access_vectors
@@ -827,6 +827,9 @@ class kernel_service
class tun_socket
inherits socket
+{
+ create_queue
+}
class x_pointer
inherits x_device
Signed-off-by: Paul Moore <redacted>
---
security/selinux/include/classmap.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
From: Paul Moore <hidden> Date: 2012-12-05 20:26:23
This patch corrects some problems with LSM/SELinux that were introduced
with the multiqueue patchset. The problem stems from the fact that the
multiqueue work changed the relationship between the tun device and its
associated socket; before the socket persisted for the life of the
device, however after the multiqueue changes the socket only persisted
for the life of the userspace connection (fd open). For non-persistent
devices this is not an issue, but for persistent devices this can cause
the tun device to lose its SELinux label.
We correct this problem by adding an opaque LSM security blob to the
tun device struct which allows us to have the LSM security state, e.g.
SELinux labeling information, persist for the lifetime of the tun
device. In the process we tweak the LSM hooks to work with this new
approach to TUN device/socket labeling and introduce a new LSM hook,
security_tun_dev_create_queue(), to approve requests to create a new
TUN queue via TUNSETQUEUE.
The SELinux code has been adjusted to match the new LSM hooks, the
other LSMs do not make use of the LSM TUN controls. This patch makes
use of the recently added "tun_socket:create_queue" permission to
restrict access to the TUNSETQUEUE operation. On older SELinux
policies which do not define the "tun_socket:create_queue" permission
the access control decision for TUNSETQUEUE will be handled according
to the SELinux policy's unknown permission setting.
Signed-off-by: Paul Moore <redacted>
---
drivers/net/tun.c | 26 +++++++++++++---
include/linux/security.h | 59 +++++++++++++++++++++++++++++--------
security/capability.c | 24 +++++++++++++--
security/security.c | 28 ++++++++++++++----
security/selinux/hooks.c | 50 ++++++++++++++++++++++++-------
security/selinux/include/objsec.h | 4 +++
6 files changed, 153 insertions(+), 38 deletions(-)
@@ -4414,8 +4432,17 @@ static int selinux_tun_dev_create(void)NULL);}-staticvoidselinux_tun_dev_post_create(structsock*sk)+staticintselinux_tun_dev_create_queue(void*security){+structtun_security_struct*tunsec=security;++returnavc_has_perm(current_sid(),tunsec->sid,SECCLASS_TUN_SOCKET,+TUN_SOCKET__CREATE_QUEUE,NULL);+}++staticintselinux_tun_dev_attach(structsock*sk,void*security)+{+structtun_security_struct*tunsec=security;structsk_security_struct*sksec=sk->sk_security;/* we don't currently perform any NetLabel based labeling here and it
@@ -4425,20 +4452,19 @@ static void selinux_tun_dev_post_create(struct sock *sk)*causeconfusiontotheTUNuserthathadnoideanetworklabeling*protocolswerebeingused*/-/* see the comments in selinux_tun_dev_create() about why we don't use-*thesockcreateSIDhere*/--sksec->sid=current_sid();+sksec->sid=tunsec->sid;sksec->sclass=SECCLASS_TUN_SOCKET;++return0;}-staticintselinux_tun_dev_attach(structsock*sk)+staticintselinux_tun_dev_open(void*security){-structsk_security_struct*sksec=sk->sk_security;+structtun_security_struct*tunsec=security;u32sid=current_sid();interr;-err=avc_has_perm(sid,sksec->sid,SECCLASS_TUN_SOCKET,+err=avc_has_perm(sid,tunsec->sid,SECCLASS_TUN_SOCKET,TUN_SOCKET__RELABELFROM,NULL);if(err)returnerr;
@@ -4446,8 +4472,7 @@ static int selinux_tun_dev_attach(struct sock *sk)TUN_SOCKET__RELABELTO,NULL);if(err)returnerr;--sksec->sid=sid;+tunsec->sid=sid;return0;}
@@ -110,6 +110,10 @@ struct sk_security_struct {u16sclass;/* sock security class */};+structtun_security_struct{+u32sid;/* SID for the tun device sockets */+};+structkey_security_struct{u32sid;/* SID of key */};
From: Jason Wang <hidden> Date: 2012-12-06 10:29:54
On Wednesday, December 05, 2012 03:26:19 PM Paul Moore wrote:
quoted hunk
This patch corrects some problems with LSM/SELinux that were introduced
with the multiqueue patchset. The problem stems from the fact that the
multiqueue work changed the relationship between the tun device and its
associated socket; before the socket persisted for the life of the
device, however after the multiqueue changes the socket only persisted
for the life of the userspace connection (fd open). For non-persistent
devices this is not an issue, but for persistent devices this can cause
the tun device to lose its SELinux label.
We correct this problem by adding an opaque LSM security blob to the
tun device struct which allows us to have the LSM security state, e.g.
SELinux labeling information, persist for the lifetime of the tun
device. In the process we tweak the LSM hooks to work with this new
approach to TUN device/socket labeling and introduce a new LSM hook,
security_tun_dev_create_queue(), to approve requests to create a new
TUN queue via TUNSETQUEUE.
The SELinux code has been adjusted to match the new LSM hooks, the
other LSMs do not make use of the LSM TUN controls. This patch makes
use of the recently added "tun_socket:create_queue" permission to
restrict access to the TUNSETQUEUE operation. On older SELinux
policies which do not define the "tun_socket:create_queue" permission
the access control decision for TUNSETQUEUE will be handled according
to the SELinux policy's unknown permission setting.
Signed-off-by: Paul Moore <redacted>
---
drivers/net/tun.c | 26 +++++++++++++---
include/linux/security.h | 59
+++++++++++++++++++++++++++++-------- security/capability.c |
24 +++++++++++++--
security/security.c | 28 ++++++++++++++----
security/selinux/hooks.c | 50 ++++++++++++++++++++++++-------
security/selinux/include/objsec.h | 4 +++
6 files changed, 153 insertions(+), 38 deletions(-)
security_mnt_opts *opts) * tells the LSM to decrement the number of
secmark
quoted hunk
labeling rules loaded * @req_classify_flow:
* Sets the flow's sid to the openreq sid.
+ * @tun_dev_alloc_security:
+ * This hook allows a module to allocate a security structure for a TUN
+ * device.
+ * @security pointer to a security structure pointer.
+ * Returns a zero on success, negative values on failure.
+ * @tun_dev_free_security:
+ * This hook allows a module to free the security structure for a TUN
+ * device.
+ * @security pointer to the TUN device's security structure
* @tun_dev_create:
* Check permissions prior to creating a new TUN device.
- * @tun_dev_post_create:
- * This hook allows a module to update or allocate a per-socket security
- * structure.
- * @sk contains the newly created sock structure.
+ * @tun_dev_create_queue:
+ * Check permissions prior to creating a new TUN device queue.
+ * @security pointer to the TUN device's security structure.
* @tun_dev_attach:
- * Check permissions prior to attaching to a persistent TUN device. This
- * hook can also be used by the module to update any security state
+ * This hook can be used by the module to update any security state
* associated with the TUN device's sock structure.
* @sk contains the existing sock structure.
+ * @security pointer to the TUN device's security structure.
+ * @tun_dev_open:
+ * This hook can be used by the module to update any security state
+ * associated with the TUN device's security structure.
+ * @security pointer to the TUN devices's security structure.
*
* Security hooks for XFRM operations.
*
*sk) * cause confusion to the TUN user that had no idea network labeling *
protocols were being used */
- /* see the comments in selinux_tun_dev_create() about why we don't use
- * the sockcreate SID here */
-
- sksec->sid = current_sid();
+ sksec->sid = tunsec->sid;
Since both tun_set_iff() and tun_set_queue() would call this. I wonder when it
is called by tun_set_queue() we need some checking just like what we done in
v1, otherwise it's unconditionally in TUNSETQUEUE. Or we can add them in
selinux_tun_dev_create_queue()?
@@ -110,6 +110,10 @@ struct sk_security_struct {u16sclass;/* sock security class */};+structtun_security_struct{+u32sid;/* SID for the tun device sockets */+};+structkey_security_struct{u32sid;/* SID of key */};--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Jason Wang <hidden> Date: 2012-12-06 10:31:29
On Wednesday, December 05, 2012 03:26:04 PM Paul Moore wrote:
quoted hunk
On error, the error code from tun_flow_init() is lost inside
tun_set_iff(), this patch fixes this by assigning the tun_flow_init()
error code to the "err" variable which is returned by
the tun_flow_init() function on error.
Signed-off-by: Paul Moore <redacted>
---
drivers/net/tun.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2012-12-06 10:33:25
On Wed, Dec 05, 2012 at 03:26:19PM -0500, Paul Moore wrote:
This patch corrects some problems with LSM/SELinux that were introduced
with the multiqueue patchset. The problem stems from the fact that the
multiqueue work changed the relationship between the tun device and its
associated socket; before the socket persisted for the life of the
device, however after the multiqueue changes the socket only persisted
for the life of the userspace connection (fd open). For non-persistent
devices this is not an issue, but for persistent devices this can cause
the tun device to lose its SELinux label.
We correct this problem by adding an opaque LSM security blob to the
tun device struct which allows us to have the LSM security state, e.g.
SELinux labeling information, persist for the lifetime of the tun
device. In the process we tweak the LSM hooks to work with this new
approach to TUN device/socket labeling and introduce a new LSM hook,
security_tun_dev_create_queue(), to approve requests to create a new
TUN queue via TUNSETQUEUE.
The SELinux code has been adjusted to match the new LSM hooks, the
other LSMs do not make use of the LSM TUN controls. This patch makes
use of the recently added "tun_socket:create_queue" permission to
restrict access to the TUNSETQUEUE operation. On older SELinux
policies which do not define the "tun_socket:create_queue" permission
the access control decision for TUNSETQUEUE will be handled according
to the SELinux policy's unknown permission setting.
Signed-off-by: Paul Moore <redacted>
OK so just to verify: this can be used to ensure that qemu
process that has the queue fd can only attach it to
a specific device, right?
@@ -4414,8 +4432,17 @@ static int selinux_tun_dev_create(void)NULL);}-staticvoidselinux_tun_dev_post_create(structsock*sk)+staticintselinux_tun_dev_create_queue(void*security){+structtun_security_struct*tunsec=security;++returnavc_has_perm(current_sid(),tunsec->sid,SECCLASS_TUN_SOCKET,+TUN_SOCKET__CREATE_QUEUE,NULL);+}++staticintselinux_tun_dev_attach(structsock*sk,void*security)+{+structtun_security_struct*tunsec=security;structsk_security_struct*sksec=sk->sk_security;/* we don't currently perform any NetLabel based labeling here and it
@@ -4425,20 +4452,19 @@ static void selinux_tun_dev_post_create(struct sock *sk)*causeconfusiontotheTUNuserthathadnoideanetworklabeling*protocolswerebeingused*/-/* see the comments in selinux_tun_dev_create() about why we don't use-*thesockcreateSIDhere*/--sksec->sid=current_sid();+sksec->sid=tunsec->sid;sksec->sclass=SECCLASS_TUN_SOCKET;++return0;}-staticintselinux_tun_dev_attach(structsock*sk)+staticintselinux_tun_dev_open(void*security){-structsk_security_struct*sksec=sk->sk_security;+structtun_security_struct*tunsec=security;u32sid=current_sid();interr;-err=avc_has_perm(sid,sksec->sid,SECCLASS_TUN_SOCKET,+err=avc_has_perm(sid,tunsec->sid,SECCLASS_TUN_SOCKET,TUN_SOCKET__RELABELFROM,NULL);if(err)returnerr;
@@ -4446,8 +4472,7 @@ static int selinux_tun_dev_attach(struct sock *sk)TUN_SOCKET__RELABELTO,NULL);if(err)returnerr;--sksec->sid=sid;+tunsec->sid=sid;return0;}
@@ -110,6 +110,10 @@ struct sk_security_struct {u16sclass;/* sock security class */};+structtun_security_struct{+u32sid;/* SID for the tun device sockets */+};+structkey_security_struct{u32sid;/* SID of key */};
From: Jason Wang <hidden> Date: 2012-12-06 13:51:19
On Thursday, December 06, 2012 12:33:25 PM Michael S. Tsirkin wrote:
On Wed, Dec 05, 2012 at 03:26:19PM -0500, Paul Moore wrote:
quoted
This patch corrects some problems with LSM/SELinux that were introduced
with the multiqueue patchset. The problem stems from the fact that the
multiqueue work changed the relationship between the tun device and its
associated socket; before the socket persisted for the life of the
device, however after the multiqueue changes the socket only persisted
for the life of the userspace connection (fd open). For non-persistent
devices this is not an issue, but for persistent devices this can cause
the tun device to lose its SELinux label.
We correct this problem by adding an opaque LSM security blob to the
tun device struct which allows us to have the LSM security state, e.g.
SELinux labeling information, persist for the lifetime of the tun
device. In the process we tweak the LSM hooks to work with this new
approach to TUN device/socket labeling and introduce a new LSM hook,
security_tun_dev_create_queue(), to approve requests to create a new
TUN queue via TUNSETQUEUE.
The SELinux code has been adjusted to match the new LSM hooks, the
other LSMs do not make use of the LSM TUN controls. This patch makes
use of the recently added "tun_socket:create_queue" permission to
restrict access to the TUNSETQUEUE operation. On older SELinux
policies which do not define the "tun_socket:create_queue" permission
the access control decision for TUNSETQUEUE will be handled according
to the SELinux policy's unknown permission setting.
Signed-off-by: Paul Moore <redacted>
OK so just to verify: this can be used to ensure that qemu
process that has the queue fd can only attach it to
a specific device, right?
I think it can't. And I'm not sure whether we need selinux help to do this.
Looks like we can do this without selinux through:
1. Don't assign a NULL pointer to tfile->tun during file detaching
2. Compare the ifr_name and the name of tfil->tun, if not equal, return -EINVAL
3. Set a special flag in tun_detach_all() to notify the fd is not usable, and
can't be used for future attaching.
Afther this, only the device that the fd is first attched through (TUNSETIFF or
TUNSETQUEUE) is allowed to be attached again.
security_mnt_opts *opts)>
* tells the LSM to decrement the number of secmark labeling rules loaded
* @req_classify_flow:
* Sets the flow's sid to the openreq sid.
+ * @tun_dev_alloc_security:
+ * This hook allows a module to allocate a security structure for a TUN
+ * device.
+ * @security pointer to a security structure pointer.
+ * Returns a zero on success, negative values on failure.
+ * @tun_dev_free_security:
+ * This hook allows a module to free the security structure for a TUN
+ * device.
+ * @security pointer to the TUN device's security structure
* @tun_dev_create:
* Check permissions prior to creating a new TUN device.
- * @tun_dev_post_create:
- * This hook allows a module to update or allocate a per-socket security
- * structure.
- * @sk contains the newly created sock structure.
+ * @tun_dev_create_queue:
+ * Check permissions prior to creating a new TUN device queue.
+ * @security pointer to the TUN device's security structure.
* @tun_dev_attach:
- * Check permissions prior to attaching to a persistent TUN device. This
- * hook can also be used by the module to update any security state
+ * This hook can be used by the module to update any security state
* associated with the TUN device's sock structure.
* @sk contains the existing sock structure.
+ * @security pointer to the TUN device's security structure.
+ * @tun_dev_open:
+ * This hook can be used by the module to update any security state
+ * associated with the TUN device's security structure.
+ * @security pointer to the TUN devices's security structure.
*
* Security hooks for XFRM operations.
*
@@ -1613,9 +1625,12 @@ struct security_operations { void (*secmark_refcount_inc) (void); void (*secmark_refcount_dec) (void); void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);> - int (*tun_dev_create)(void);- void (*tun_dev_post_create)(struct sock *sk);- int (*tun_dev_attach)(struct sock *sk);+ int (*tun_dev_alloc_security) (void **security);+ void (*tun_dev_free_security) (void *security);+ int (*tun_dev_create) (void);+ int (*tun_dev_create_queue) (void *security);+ int (*tun_dev_attach) (struct sock *sk, void *security);+ int (*tun_dev_open) (void *security); #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM
sock *sk)>
* cause confusion to the TUN user that had no idea network labeling
* protocols were being used */
- /* see the comments in selinux_tun_dev_create() about why we don't use
- * the sockcreate SID here */
-
- sksec->sid = current_sid();
+ sksec->sid = tunsec->sid;
sksec->sclass = SECCLASS_TUN_SOCKET;
+
+ return 0;
}
-static int selinux_tun_dev_attach(struct sock *sk)
+static int selinux_tun_dev_open(void *security)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct tun_security_struct *tunsec = security;
u32 sid = current_sid();
int err;
- err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET,
+ err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
TUN_SOCKET__RELABELFROM, NULL);
if (err)
return err;
@@ -110,6 +110,10 @@ struct sk_security_struct {u16sclass;/* sock security class */};+structtun_security_struct{+u32sid;/* SID for the tun device sockets */+};+structkey_security_struct{u32sid;/* SID of key */};
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2012-12-06 14:12:20
On Thu, Dec 06, 2012 at 09:51:13PM +0800, Jason Wang wrote:
On Thursday, December 06, 2012 12:33:25 PM Michael S. Tsirkin wrote:
quoted
On Wed, Dec 05, 2012 at 03:26:19PM -0500, Paul Moore wrote:
quoted
This patch corrects some problems with LSM/SELinux that were introduced
with the multiqueue patchset. The problem stems from the fact that the
multiqueue work changed the relationship between the tun device and its
associated socket; before the socket persisted for the life of the
device, however after the multiqueue changes the socket only persisted
for the life of the userspace connection (fd open). For non-persistent
devices this is not an issue, but for persistent devices this can cause
the tun device to lose its SELinux label.
We correct this problem by adding an opaque LSM security blob to the
tun device struct which allows us to have the LSM security state, e.g.
SELinux labeling information, persist for the lifetime of the tun
device. In the process we tweak the LSM hooks to work with this new
approach to TUN device/socket labeling and introduce a new LSM hook,
security_tun_dev_create_queue(), to approve requests to create a new
TUN queue via TUNSETQUEUE.
The SELinux code has been adjusted to match the new LSM hooks, the
other LSMs do not make use of the LSM TUN controls. This patch makes
use of the recently added "tun_socket:create_queue" permission to
restrict access to the TUNSETQUEUE operation. On older SELinux
policies which do not define the "tun_socket:create_queue" permission
the access control decision for TUNSETQUEUE will be handled according
to the SELinux policy's unknown permission setting.
Signed-off-by: Paul Moore <redacted>
OK so just to verify: this can be used to ensure that qemu
process that has the queue fd can only attach it to
a specific device, right?
I think it can't.
And I'm not sure whether we need selinux help to do this.
Well without selinux I doi not see a problem.
If you can do SETQUEUE you can do SETIFF too and then
you can attach to tap.
Looks like we can do this without selinux through:
1. Don't assign a NULL pointer to tfile->tun during file detaching
So you detach from tun but keep a pointer to it? Not good.
2. Compare the ifr_name and the name of tfil->tun, if not equal, return -EINVAL
3. Set a special flag in tun_detach_all() to notify the fd is not usable, and
can't be used for future attaching.
Afther this, only the device that the fd is first attched through (TUNSETIFF or
TUNSETQUEUE) is allowed to be attached again.
This looks like a hard-coded security policy.
The problem is not detach the problem is attach,
we should solve it there.
security_mnt_opts *opts)>
* tells the LSM to decrement the number of secmark labeling rules loaded
* @req_classify_flow:
* Sets the flow's sid to the openreq sid.
+ * @tun_dev_alloc_security:
+ * This hook allows a module to allocate a security structure for a TUN
+ * device.
+ * @security pointer to a security structure pointer.
+ * Returns a zero on success, negative values on failure.
+ * @tun_dev_free_security:
+ * This hook allows a module to free the security structure for a TUN
+ * device.
+ * @security pointer to the TUN device's security structure
* @tun_dev_create:
* Check permissions prior to creating a new TUN device.
- * @tun_dev_post_create:
- * This hook allows a module to update or allocate a per-socket security
- * structure.
- * @sk contains the newly created sock structure.
+ * @tun_dev_create_queue:
+ * Check permissions prior to creating a new TUN device queue.
+ * @security pointer to the TUN device's security structure.
* @tun_dev_attach:
- * Check permissions prior to attaching to a persistent TUN device. This
- * hook can also be used by the module to update any security state
+ * This hook can be used by the module to update any security state
* associated with the TUN device's sock structure.
* @sk contains the existing sock structure.
+ * @security pointer to the TUN device's security structure.
+ * @tun_dev_open:
+ * This hook can be used by the module to update any security state
+ * associated with the TUN device's security structure.
+ * @security pointer to the TUN devices's security structure.
*
* Security hooks for XFRM operations.
*
@@ -1613,9 +1625,12 @@ struct security_operations { void (*secmark_refcount_inc) (void); void (*secmark_refcount_dec) (void); void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);> - int (*tun_dev_create)(void);- void (*tun_dev_post_create)(struct sock *sk);- int (*tun_dev_attach)(struct sock *sk);+ int (*tun_dev_alloc_security) (void **security);+ void (*tun_dev_free_security) (void *security);+ int (*tun_dev_create) (void);+ int (*tun_dev_create_queue) (void *security);+ int (*tun_dev_attach) (struct sock *sk, void *security);+ int (*tun_dev_open) (void *security); #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM
sock *sk)>
* cause confusion to the TUN user that had no idea network labeling
* protocols were being used */
- /* see the comments in selinux_tun_dev_create() about why we don't use
- * the sockcreate SID here */
-
- sksec->sid = current_sid();
+ sksec->sid = tunsec->sid;
sksec->sclass = SECCLASS_TUN_SOCKET;
+
+ return 0;
}
-static int selinux_tun_dev_attach(struct sock *sk)
+static int selinux_tun_dev_open(void *security)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct tun_security_struct *tunsec = security;
u32 sid = current_sid();
int err;
- err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET,
+ err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
TUN_SOCKET__RELABELFROM, NULL);
if (err)
return err;
@@ -110,6 +110,10 @@ struct sk_security_struct {u16sclass;/* sock security class */};+structtun_security_struct{+u32sid;/* SID for the tun device sockets */+};+structkey_security_struct{u32sid;/* SID of key */};
From: Paul Moore <hidden> Date: 2012-12-06 15:36:15
On Thursday, December 06, 2012 06:29:54 PM Jason Wang wrote:
On Wednesday, December 05, 2012 03:26:19 PM Paul Moore wrote:
quoted
This patch corrects some problems with LSM/SELinux that were introduced
with the multiqueue patchset. The problem stems from the fact that the
multiqueue work changed the relationship between the tun device and its
associated socket; before the socket persisted for the life of the
device, however after the multiqueue changes the socket only persisted
for the life of the userspace connection (fd open). For non-persistent
devices this is not an issue, but for persistent devices this can cause
the tun device to lose its SELinux label.
We correct this problem by adding an opaque LSM security blob to the
tun device struct which allows us to have the LSM security state, e.g.
SELinux labeling information, persist for the lifetime of the tun
device. In the process we tweak the LSM hooks to work with this new
approach to TUN device/socket labeling and introduce a new LSM hook,
security_tun_dev_create_queue(), to approve requests to create a new
TUN queue via TUNSETQUEUE.
The SELinux code has been adjusted to match the new LSM hooks, the
other LSMs do not make use of the LSM TUN controls. This patch makes
use of the recently added "tun_socket:create_queue" permission to
restrict access to the TUNSETQUEUE operation. On older SELinux
policies which do not define the "tun_socket:create_queue" permission
the access control decision for TUNSETQUEUE will be handled according
to the SELinux policy's unknown permission setting.
Signed-off-by: Paul Moore <redacted>
sock
*sk) * cause confusion to the TUN user that had no idea network labeling *
protocols were being used */
- /* see the comments in selinux_tun_dev_create() about why we ...
-
- sksec->sid = current_sid();
+ sksec->sid = tunsec->sid;
Since both tun_set_iff() and tun_set_queue() would call this. I wonder when
it is called by tun_set_queue() we need some checking just like what we
done in v1, otherwise it's unconditionally in TUNSETQUEUE. Or we can add
them in selinux_tun_dev_create_queue()?
In all the cases that call tun_attach() we have a new socket which needs to be
labeled based on the tun->security label, yes? That is what the
security_tun_dev_attach() code does, there is no need for access control at
this point as the operation has already been authorized by either
security_tun_dev_create() (new device), security_tun_dev_create_queue() (new
queue), or security_tun_dev_open() (opening persistent device).
I think we are all set, or am I missing something?
From: Paul Moore <hidden> Date: 2012-12-06 15:46:11
On Thursday, December 06, 2012 12:33:25 PM Michael S. Tsirkin wrote:
On Wed, Dec 05, 2012 at 03:26:19PM -0500, Paul Moore wrote:
quoted
This patch corrects some problems with LSM/SELinux that were introduced
with the multiqueue patchset. The problem stems from the fact that the
multiqueue work changed the relationship between the tun device and its
associated socket; before the socket persisted for the life of the
device, however after the multiqueue changes the socket only persisted
for the life of the userspace connection (fd open). For non-persistent
devices this is not an issue, but for persistent devices this can cause
the tun device to lose its SELinux label.
We correct this problem by adding an opaque LSM security blob to the
tun device struct which allows us to have the LSM security state, e.g.
SELinux labeling information, persist for the lifetime of the tun
device. In the process we tweak the LSM hooks to work with this new
approach to TUN device/socket labeling and introduce a new LSM hook,
security_tun_dev_create_queue(), to approve requests to create a new
TUN queue via TUNSETQUEUE.
The SELinux code has been adjusted to match the new LSM hooks, the
other LSMs do not make use of the LSM TUN controls. This patch makes
use of the recently added "tun_socket:create_queue" permission to
restrict access to the TUNSETQUEUE operation. On older SELinux
policies which do not define the "tun_socket:create_queue" permission
the access control decision for TUNSETQUEUE will be handled according
to the SELinux policy's unknown permission setting.
Signed-off-by: Paul Moore <redacted>
OK so just to verify: this can be used to ensure that qemu
process that has the queue fd can only attach it to
a specific device, right?
Whenever a new queue is created via TUNSETQUEUE/tun_set_queue() the
security_tun_dev_create_queue() LSM hook is called. When SELinux is enabled
this hook ends up calling selinux_tun_dev_create_queue() which checks that the
calling process (process_t) is allowed to create a new queue on the specified
device (tundev_t) . If you are familiar with SELinux security policy, the
allow rule would look like this:
allow process_t tundev_t:tun_socket create_queue;
In practice, if we assume libvirt is creating the TUN device and running with
a SELinux label of virtd_t and that QEMU instances are running with a SELinux
label of svirt_t then the allow rule would look like this:
allow svirt_t virtd_t:tun_socket create_queue;
There is also the matter of the MLS/MCS constraints providing additional
separation but that is another level of detail which I don't believe is
important for our discussion.
--
paul moore
security and virtualization @ redhat
From: Paul Moore <hidden> Date: 2012-12-06 15:46:42
On Thursday, December 06, 2012 06:31:29 PM Jason Wang wrote:
On Wednesday, December 05, 2012 03:26:04 PM Paul Moore wrote:
quoted
On error, the error code from tun_flow_init() is lost inside
tun_set_iff(), this patch fixes this by assigning the tun_flow_init()
error code to the "err" variable which is returned by
the tun_flow_init() function on error.
Signed-off-by: Paul Moore <redacted>
---
drivers/net/tun.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2012-12-06 16:12:00
On Thu, Dec 06, 2012 at 10:46:11AM -0500, Paul Moore wrote:
On Thursday, December 06, 2012 12:33:25 PM Michael S. Tsirkin wrote:
quoted
On Wed, Dec 05, 2012 at 03:26:19PM -0500, Paul Moore wrote:
quoted
This patch corrects some problems with LSM/SELinux that were introduced
with the multiqueue patchset. The problem stems from the fact that the
multiqueue work changed the relationship between the tun device and its
associated socket; before the socket persisted for the life of the
device, however after the multiqueue changes the socket only persisted
for the life of the userspace connection (fd open). For non-persistent
devices this is not an issue, but for persistent devices this can cause
the tun device to lose its SELinux label.
We correct this problem by adding an opaque LSM security blob to the
tun device struct which allows us to have the LSM security state, e.g.
SELinux labeling information, persist for the lifetime of the tun
device. In the process we tweak the LSM hooks to work with this new
approach to TUN device/socket labeling and introduce a new LSM hook,
security_tun_dev_create_queue(), to approve requests to create a new
TUN queue via TUNSETQUEUE.
The SELinux code has been adjusted to match the new LSM hooks, the
other LSMs do not make use of the LSM TUN controls. This patch makes
use of the recently added "tun_socket:create_queue" permission to
restrict access to the TUNSETQUEUE operation. On older SELinux
policies which do not define the "tun_socket:create_queue" permission
the access control decision for TUNSETQUEUE will be handled according
to the SELinux policy's unknown permission setting.
Signed-off-by: Paul Moore <redacted>
OK so just to verify: this can be used to ensure that qemu
process that has the queue fd can only attach it to
a specific device, right?
Whenever a new queue is created via TUNSETQUEUE/tun_set_queue() the
security_tun_dev_create_queue() LSM hook is called. When SELinux is enabled
this hook ends up calling selinux_tun_dev_create_queue() which checks that the
calling process (process_t) is allowed to create a new queue on the specified
device (tundev_t) . If you are familiar with SELinux security policy, the
allow rule would look like this:
allow process_t tundev_t:tun_socket create_queue;
In practice, if we assume libvirt is creating the TUN device and running with
a SELinux label of virtd_t and that QEMU instances are running with a SELinux
label of svirt_t then the allow rule would look like this:
allow svirt_t virtd_t:tun_socket create_queue;
There is also the matter of the MLS/MCS constraints providing additional
separation but that is another level of detail which I don't believe is
important for our discussion.
Hmm. How do the rules for SETIFF look ATM?
I am just checking default policy does not let qemu do with
SETQUEUE something with a device which it can not
attach to using SETIFF.
--
paul moore
security and virtualization @ redhat
From: Paul Moore <hidden> Date: 2012-12-06 16:57:10
On Thursday, December 06, 2012 06:12:00 PM Michael S. Tsirkin wrote:
On Thu, Dec 06, 2012 at 10:46:11AM -0500, Paul Moore wrote:
quoted
On Thursday, December 06, 2012 12:33:25 PM Michael S. Tsirkin wrote:
quoted
OK so just to verify: this can be used to ensure that qemu
process that has the queue fd can only attach it to
a specific device, right?
Whenever a new queue is created via TUNSETQUEUE/tun_set_queue() the
security_tun_dev_create_queue() LSM hook is called. When SELinux is
enabled this hook ends up calling selinux_tun_dev_create_queue() which
checks that the calling process (process_t) is allowed to create a new
queue on the specified device (tundev_t) . If you are familiar with
SELinux security policy, the allow rule would look like this:
allow process_t tundev_t:tun_socket create_queue;
In practice, if we assume libvirt is creating the TUN device and running
with a SELinux label of virtd_t and that QEMU instances are running with
a SELinux label of svirt_t then the allow rule would look like this:
allow svirt_t virtd_t:tun_socket create_queue;
There is also the matter of the MLS/MCS constraints providing additional
separation but that is another level of detail which I don't believe is
important for our discussion.
Hmm. How do the rules for SETIFF look ATM?
I am just checking default policy does not let qemu do with
SETQUEUE something with a device which it can not
attach to using SETIFF.
The SETQUEUE/tun_socket:create_queue permissions do not yet exist in any
released SELinux policy as we are just now adding them with this patchset.
With current policies loaded into a kernel with this patchset applied the
SETQUEUE/tun_socket:create_queue permission would be treated according to the
policy's unknown permission setting.
--
paul moore
security and virtualization @ redhat
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2012-12-06 20:57:16
On Thu, Dec 06, 2012 at 11:56:45AM -0500, Paul Moore wrote:
The SETQUEUE/tun_socket:create_queue permissions do not yet exist in any
released SELinux policy as we are just now adding them with this patchset.
With current policies loaded into a kernel with this patchset applied the
SETQUEUE/tun_socket:create_queue permission would be treated according to the
policy's unknown permission setting.
OK I think we need to rethink what we are doing here: what you sent
addresses the problem as stated but I think we mis-stated it. Let me
try to restate the problem: it is not just selinux problem. Let's
assume qemu wants to use tun, I (libvirt) don't want to run it as root.
1. TUNSETIFF: I can open tun, attach an fd and pass it to qemu.
Now, qemu does not invoke TUNSETIFF so it can run without
kernel priveledges.
2. TUNSETQUEUE - I can open tun and attach a queue but this
is not what is needed since this automatically switches
to multiqueue mode - we want to change number of queues
on the fly.
So qemu needs to be allowed to run TUNSETQUEUE.
Since this checks tun_not_capable(tun) we would need
to give qemu these priveledges, and we want to avoid this
(I can go into why if it's not obvious).
How can we slove this?
I don't see a way without extending the interface.
Here's a simple way to extend it: pass a flag to TUNSETQUEUE
that enables/disables TX on this queue.
If TX is disabled, ignore this queue for flow steering decisions.
Allow TUNSETQUEUE for a non priveledged user if it
it already bound to the currect tun and only changes this flag.
Now I open tun and SETQUEUE with TX disabled flag. Pass it to qemu.
qemu calls SETQUEUE with TX enabled flag.
Jason? Want to try implementing and see what people think?
--
paul moore
security and virtualization @ redhat
From: Paul Moore <hidden> Date: 2012-12-06 21:09:54
On Thursday, December 06, 2012 10:57:16 PM Michael S. Tsirkin wrote:
On Thu, Dec 06, 2012 at 11:56:45AM -0500, Paul Moore wrote:
quoted
The SETQUEUE/tun_socket:create_queue permissions do not yet exist in any
released SELinux policy as we are just now adding them with this patchset.
With current policies loaded into a kernel with this patchset applied the
SETQUEUE/tun_socket:create_queue permission would be treated according to
the policy's unknown permission setting.
OK I think we need to rethink what we are doing here: what you sent
addresses the problem as stated but I think we mis-stated it. Let me
try to restate the problem: it is not just selinux problem. Let's assume
qemu wants to use tun, I (libvirt) don't want to run it as root.
1. TUNSETIFF: I can open tun, attach an fd and pass it to qemu.
Now, qemu does not invoke TUNSETIFF so it can run without
kernel priveledges.
Correct me if I'm wrong, but I believe libvirt does this while running as
root. Assuming that is the case, why not simply setuid()/setgid() to the same
credentials as the QEMU instance before creating the TUN device? You can
always (re)configure the device afterwards while running as
root/CAP_NET_ADMIN.
2. TUNSETQUEUE - I can open tun and attach a queue but this
is not what is needed since this automatically switches
to multiqueue mode - we want to change number of queues
on the fly.
So qemu needs to be allowed to run TUNSETQUEUE.
Since this checks tun_not_capable(tun) we would need
to give qemu these priveledges, and we want to avoid this
(I can go into why if it's not obvious).
If libvirt creates the TUN device while its effective credentials match those
of the QEMU instance then the QEMU instance should be able to perform a
TUNSETQUEUE, yes?
How can we slove this?
I don't see a way without extending the interface.
Here's a simple way to extend it: pass a flag to TUNSETQUEUE
that enables/disables TX on this queue.
If TX is disabled, ignore this queue for flow steering decisions.
Allow TUNSETQUEUE for a non priveledged user if it
it already bound to the currect tun and only changes this flag.
Now I open tun and SETQUEUE with TX disabled flag. Pass it to qemu.
qemu calls SETQUEUE with TX enabled flag.
Jason? Want to try implementing and see what people think?
--
paul moore
security and virtualization @ redhat
From: Jason Wang <hidden> Date: 2012-12-07 05:29:29
On Thursday, December 06, 2012 10:36:11 AM Paul Moore wrote:
On Thursday, December 06, 2012 06:29:54 PM Jason Wang wrote:
quoted
On Wednesday, December 05, 2012 03:26:19 PM Paul Moore wrote:
quoted
This patch corrects some problems with LSM/SELinux that were introduced
with the multiqueue patchset. The problem stems from the fact that the
multiqueue work changed the relationship between the tun device and its
associated socket; before the socket persisted for the life of the
device, however after the multiqueue changes the socket only persisted
for the life of the userspace connection (fd open). For non-persistent
devices this is not an issue, but for persistent devices this can cause
the tun device to lose its SELinux label.
We correct this problem by adding an opaque LSM security blob to the
tun device struct which allows us to have the LSM security state, e.g.
SELinux labeling information, persist for the lifetime of the tun
device. In the process we tweak the LSM hooks to work with this new
approach to TUN device/socket labeling and introduce a new LSM hook,
security_tun_dev_create_queue(), to approve requests to create a new
TUN queue via TUNSETQUEUE.
The SELinux code has been adjusted to match the new LSM hooks, the
other LSMs do not make use of the LSM TUN controls. This patch makes
use of the recently added "tun_socket:create_queue" permission to
restrict access to the TUNSETQUEUE operation. On older SELinux
policies which do not define the "tun_socket:create_queue" permission
the access control decision for TUNSETQUEUE will be handled according
to the SELinux policy's unknown permission setting.
Signed-off-by: Paul Moore <redacted>
sock
*sk) * cause confusion to the TUN user that had no idea network labeling
*
protocols were being used */
- /* see the comments in selinux_tun_dev_create() about why we ...
-
- sksec->sid = current_sid();
+ sksec->sid = tunsec->sid;
Since both tun_set_iff() and tun_set_queue() would call this. I wonder
when
it is called by tun_set_queue() we need some checking just like what we
done in v1, otherwise it's unconditionally in TUNSETQUEUE. Or we can add
them in selinux_tun_dev_create_queue()?
In all the cases that call tun_attach() we have a new socket which needs to
be labeled based on the tun->security label, yes? That is what the
Yes.
security_tun_dev_attach() code does, there is no need for access control at
this point as the operation has already been authorized by either
security_tun_dev_create() (new device), security_tun_dev_create_queue() (new
queue), or security_tun_dev_open() (opening persistent device).
I think we are all set, or am I missing something?
From: Jason Wang <hidden> Date: 2012-12-07 05:41:54
On Thursday, December 06, 2012 10:57:16 PM Michael S. Tsirkin wrote:
On Thu, Dec 06, 2012 at 11:56:45AM -0500, Paul Moore wrote:
quoted
The SETQUEUE/tun_socket:create_queue permissions do not yet exist in any
released SELinux policy as we are just now adding them with this patchset.
With current policies loaded into a kernel with this patchset applied the
SETQUEUE/tun_socket:create_queue permission would be treated according to
the policy's unknown permission setting.
OK I think we need to rethink what we are doing here: what you sent
addresses the problem as stated but I think we mis-stated it. Let me
try to restate the problem: it is not just selinux problem. Let's
assume qemu wants to use tun, I (libvirt) don't want to run it as root.
1. TUNSETIFF: I can open tun, attach an fd and pass it to qemu.
Now, qemu does not invoke TUNSETIFF so it can run without
kernel priveledges.
2. TUNSETQUEUE - I can open tun and attach a queue but this
is not what is needed since this automatically switches
to multiqueue mode - we want to change number of queues
on the fly.
So qemu needs to be allowed to run TUNSETQUEUE.
Since this checks tun_not_capable(tun) we would need
to give qemu these priveledges, and we want to avoid this
(I can go into why if it's not obvious).
How can we slove this?
I don't see a way without extending the interface.
Here's a simple way to extend it: pass a flag to TUNSETQUEUE
that enables/disables TX on this queue.
If TX is disabled, ignore this queue for flow steering decisions.
Allow TUNSETQUEUE for a non priveledged user if it
it already bound to the currect tun and only changes this flag.
Now I open tun and SETQUEUE with TX disabled flag. Pass it to qemu.
qemu calls SETQUEUE with TX enabled flag.
So the check of CAP_NET_ADMIN is bypassed in the situation. And new selinux
policy is then needed for this new flag.
The only concern with this is whether it could be treated as a kind of host
network device configuration and need CAP_NET_ADMIN capability. (But it looks
the only method that we could let qemu change the queue used by tun).
Jason? Want to try implementing and see what people think?
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2012-12-07 12:25:16
On Thu, Dec 06, 2012 at 04:09:51PM -0500, Paul Moore wrote:
On Thursday, December 06, 2012 10:57:16 PM Michael S. Tsirkin wrote:
quoted
On Thu, Dec 06, 2012 at 11:56:45AM -0500, Paul Moore wrote:
quoted
The SETQUEUE/tun_socket:create_queue permissions do not yet exist in any
released SELinux policy as we are just now adding them with this patchset.
With current policies loaded into a kernel with this patchset applied the
SETQUEUE/tun_socket:create_queue permission would be treated according to
the policy's unknown permission setting.
OK I think we need to rethink what we are doing here: what you sent
addresses the problem as stated but I think we mis-stated it. Let me
try to restate the problem: it is not just selinux problem. Let's assume
qemu wants to use tun, I (libvirt) don't want to run it as root.
1. TUNSETIFF: I can open tun, attach an fd and pass it to qemu.
Now, qemu does not invoke TUNSETIFF so it can run without
kernel priveledges.
Correct me if I'm wrong, but I believe libvirt does this while running as
root. Assuming that is the case, why not simply setuid()/setgid() to the same
credentials as the QEMU instance before creating the TUN device? You can
always (re)configure the device afterwards while running as
root/CAP_NET_ADMIN.
We want isolation between qemu instances.
Giving qemu right to open tun and SETIFF would give it rights
to access any tun device.
There could also be user tun users we want them isolated from qemu.
quoted
2. TUNSETQUEUE - I can open tun and attach a queue but this
is not what is needed since this automatically switches
to multiqueue mode - we want to change number of queues
on the fly.
So qemu needs to be allowed to run TUNSETQUEUE.
Since this checks tun_not_capable(tun) we would need
to give qemu these priveledges, and we want to avoid this
(I can go into why if it's not obvious).
If libvirt creates the TUN device while its effective credentials match those
of the QEMU instance then the QEMU instance should be able to perform a
TUNSETQUEUE, yes?
quoted
How can we slove this?
I don't see a way without extending the interface.
Here's a simple way to extend it: pass a flag to TUNSETQUEUE
that enables/disables TX on this queue.
If TX is disabled, ignore this queue for flow steering decisions.
Allow TUNSETQUEUE for a non priveledged user if it
it already bound to the currect tun and only changes this flag.
Now I open tun and SETQUEUE with TX disabled flag. Pass it to qemu.
qemu calls SETQUEUE with TX enabled flag.
Jason? Want to try implementing and see what people think?
--
paul moore
security and virtualization @ redhat
From: Paul Moore <hidden> Date: 2012-12-10 17:04:35
On Friday, December 07, 2012 02:25:16 PM Michael S. Tsirkin wrote:
On Thu, Dec 06, 2012 at 04:09:51PM -0500, Paul Moore wrote:
quoted
On Thursday, December 06, 2012 10:57:16 PM Michael S. Tsirkin wrote:
quoted
On Thu, Dec 06, 2012 at 11:56:45AM -0500, Paul Moore wrote:
quoted
The SETQUEUE/tun_socket:create_queue permissions do not yet exist in
any released SELinux policy as we are just now adding them with this
patchset. With current policies loaded into a kernel with this
patchset applied the SETQUEUE/tun_socket:create_queue permission would
be treated according to the policy's unknown permission setting.
OK I think we need to rethink what we are doing here: what you sent
addresses the problem as stated but I think we mis-stated it. Let me
try to restate the problem: it is not just selinux problem. Let's assume
qemu wants to use tun, I (libvirt) don't want to run it as root.
1. TUNSETIFF: I can open tun, attach an fd and pass it to qemu.
Now, qemu does not invoke TUNSETIFF so it can run without
kernel priveledges.
Correct me if I'm wrong, but I believe libvirt does this while running as
root. Assuming that is the case, why not simply setuid()/setgid() to the
same credentials as the QEMU instance before creating the TUN device?
You can always (re)configure the device afterwards while running as
root/CAP_NET_ADMIN.
We want isolation between qemu instances.
Understood, I agree.
Achieving separation via SELinux is easily done, with libvirt/sVirt already
doing this for us automatically in most cases; the only thing we will want to
do is make sure the SELinux policy is aware of the new permission.
Achieving separation via DAC should also be easily done, simply run each QEMU
instance with a separate UID and/or GID.
Giving qemu right to open tun and SETIFF would give it rights
to access any tun device.
I'm quickly looked at tun_chr_open() again and I don't see any special
rights/privileges required, the same for tun_chr_ioctl() and
__tun_chr_ioctl(). Looking at tun_set_queue() I see we call tun_not_capable()
which does a simple DAC check; it must have the same UID/GID or have
CAP_NET_ADMIN.
I'm having a hard time seeing the problem you are describing; help me
understand.
There could also be user tun users we want them isolated from qemu.
Once again, should be possible using either SELinux, DAC, or both.
--
paul moore
security and virtualization @ redhat
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2012-12-10 17:26:56
On Mon, Dec 10, 2012 at 12:04:35PM -0500, Paul Moore wrote:
On Friday, December 07, 2012 02:25:16 PM Michael S. Tsirkin wrote:
quoted
On Thu, Dec 06, 2012 at 04:09:51PM -0500, Paul Moore wrote:
quoted
On Thursday, December 06, 2012 10:57:16 PM Michael S. Tsirkin wrote:
quoted
On Thu, Dec 06, 2012 at 11:56:45AM -0500, Paul Moore wrote:
quoted
The SETQUEUE/tun_socket:create_queue permissions do not yet exist in
any released SELinux policy as we are just now adding them with this
patchset. With current policies loaded into a kernel with this
patchset applied the SETQUEUE/tun_socket:create_queue permission would
be treated according to the policy's unknown permission setting.
OK I think we need to rethink what we are doing here: what you sent
addresses the problem as stated but I think we mis-stated it. Let me
try to restate the problem: it is not just selinux problem. Let's assume
qemu wants to use tun, I (libvirt) don't want to run it as root.
1. TUNSETIFF: I can open tun, attach an fd and pass it to qemu.
Now, qemu does not invoke TUNSETIFF so it can run without
kernel priveledges.
Correct me if I'm wrong, but I believe libvirt does this while running as
root. Assuming that is the case, why not simply setuid()/setgid() to the
same credentials as the QEMU instance before creating the TUN device?
You can always (re)configure the device afterwards while running as
root/CAP_NET_ADMIN.
We want isolation between qemu instances.
Understood, I agree.
Achieving separation via SELinux is easily done, with libvirt/sVirt already
doing this for us automatically in most cases; the only thing we will want to
do is make sure the SELinux policy is aware of the new permission.
Achieving separation via DAC should also be easily done, simply run each QEMU
instance with a separate UID and/or GID.
quoted
Giving qemu right to open tun and SETIFF would give it rights
to access any tun device.
I'm quickly looked at tun_chr_open() again and I don't see any special
rights/privileges required, the same for tun_chr_ioctl() and
__tun_chr_ioctl(). Looking at tun_set_queue() I see we call tun_not_capable()
which does a simple DAC check; it must have the same UID/GID or have
CAP_NET_ADMIN.
I'm having a hard time seeing the problem you are describing; help me
understand.
The issue is guest controls the number of queues in use.
So qemu would be required to be allowed to call tun_set_queue.
If we allow this we have a problem as one qemu will be
able to access any tun.
At least with DAC, looks like there's a problem. SELinux I think
can address this.
quoted
There could also be user tun users we want them isolated from qemu.
Once again, should be possible using either SELinux, DAC, or both.
--
paul moore
security and virtualization @ redhat
From: Paul Moore <hidden> Date: 2012-12-10 17:33:53
On Monday, December 10, 2012 07:26:56 PM Michael S. Tsirkin wrote:
On Mon, Dec 10, 2012 at 12:04:35PM -0500, Paul Moore wrote:
quoted
On Friday, December 07, 2012 02:25:16 PM Michael S. Tsirkin wrote:
quoted
On Thu, Dec 06, 2012 at 04:09:51PM -0500, Paul Moore wrote:
quoted
On Thursday, December 06, 2012 10:57:16 PM Michael S. Tsirkin wrote:
quoted
On Thu, Dec 06, 2012 at 11:56:45AM -0500, Paul Moore wrote:
quoted
The SETQUEUE/tun_socket:create_queue permissions do not yet exist
in any released SELinux policy as we are just now adding them with
this patchset. With current policies loaded into a kernel with
this patchset applied the SETQUEUE/tun_socket:create_queue
permission would be treated according to the policy's unknown
permission setting.
OK I think we need to rethink what we are doing here: what you sent
addresses the problem as stated but I think we mis-stated it. Let
me try to restate the problem: it is not just selinux problem. Let's
assume qemu wants to use tun, I (libvirt) don't want to run it as
root.
1. TUNSETIFF: I can open tun, attach an fd and pass it to qemu.
Now, qemu does not invoke TUNSETIFF so it can run without
kernel priveledges.
Correct me if I'm wrong, but I believe libvirt does this while running
as root. Assuming that is the case, why not simply setuid()/setgid()
to the same credentials as the QEMU instance before creating the TUN
device? You can always (re)configure the device afterwards while
running as root/CAP_NET_ADMIN.
We want isolation between qemu instances.
Understood, I agree.
Achieving separation via SELinux is easily done, with libvirt/sVirt
already doing this for us automatically in most cases; the only thing we
will want to do is make sure the SELinux policy is aware of the new
permission.
Achieving separation via DAC should also be easily done, simply run each
QEMU instance with a separate UID and/or GID.
quoted
Giving qemu right to open tun and SETIFF would give it rights
to access any tun device.
I'm quickly looked at tun_chr_open() again and I don't see any special
rights/privileges required, the same for tun_chr_ioctl() and
__tun_chr_ioctl(). Looking at tun_set_queue() I see we call
tun_not_capable() which does a simple DAC check; it must have the same
UID/GID or have CAP_NET_ADMIN.
I'm having a hard time seeing the problem you are describing; help me
understand.
The issue is guest controls the number of queues in use.
So qemu would be required to be allowed to call tun_set_queue.
If we allow this we have a problem as one qemu will be
able to access any tun.
QEMU can call tun_set_queue() as long as it satisfies tun_not_capable(), which
from a practical point of view means that the TUN device was created with the
same UID/GID as the QEMU instance. If you want TUN device separation between
QEMU instances using DAC you need to run each QEMU instance with a different
UID/GID (which you should be doing anyway if you want DAC enforced general
separation).
I believe I've stated this point several times now and I don't feel you've
addressed it properly.
--
paul moore
security and virtualization @ redhat
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2012-12-10 17:50:35
On Mon, Dec 10, 2012 at 12:33:49PM -0500, Paul Moore wrote:
On Monday, December 10, 2012 07:26:56 PM Michael S. Tsirkin wrote:
quoted
On Mon, Dec 10, 2012 at 12:04:35PM -0500, Paul Moore wrote:
quoted
On Friday, December 07, 2012 02:25:16 PM Michael S. Tsirkin wrote:
quoted
On Thu, Dec 06, 2012 at 04:09:51PM -0500, Paul Moore wrote:
quoted
On Thursday, December 06, 2012 10:57:16 PM Michael S. Tsirkin wrote:
quoted
On Thu, Dec 06, 2012 at 11:56:45AM -0500, Paul Moore wrote:
quoted
The SETQUEUE/tun_socket:create_queue permissions do not yet exist
in any released SELinux policy as we are just now adding them with
this patchset. With current policies loaded into a kernel with
this patchset applied the SETQUEUE/tun_socket:create_queue
permission would be treated according to the policy's unknown
permission setting.
OK I think we need to rethink what we are doing here: what you sent
addresses the problem as stated but I think we mis-stated it. Let
me try to restate the problem: it is not just selinux problem. Let's
assume qemu wants to use tun, I (libvirt) don't want to run it as
root.
1. TUNSETIFF: I can open tun, attach an fd and pass it to qemu.
Now, qemu does not invoke TUNSETIFF so it can run without
kernel priveledges.
Correct me if I'm wrong, but I believe libvirt does this while running
as root. Assuming that is the case, why not simply setuid()/setgid()
to the same credentials as the QEMU instance before creating the TUN
device? You can always (re)configure the device afterwards while
running as root/CAP_NET_ADMIN.
We want isolation between qemu instances.
Understood, I agree.
Achieving separation via SELinux is easily done, with libvirt/sVirt
already doing this for us automatically in most cases; the only thing we
will want to do is make sure the SELinux policy is aware of the new
permission.
Achieving separation via DAC should also be easily done, simply run each
QEMU instance with a separate UID and/or GID.
quoted
Giving qemu right to open tun and SETIFF would give it rights
to access any tun device.
I'm quickly looked at tun_chr_open() again and I don't see any special
rights/privileges required, the same for tun_chr_ioctl() and
__tun_chr_ioctl(). Looking at tun_set_queue() I see we call
tun_not_capable() which does a simple DAC check; it must have the same
UID/GID or have CAP_NET_ADMIN.
I'm having a hard time seeing the problem you are describing; help me
understand.
The issue is guest controls the number of queues in use.
So qemu would be required to be allowed to call tun_set_queue.
If we allow this we have a problem as one qemu will be
able to access any tun.
QEMU can call tun_set_queue() as long as it satisfies tun_not_capable(), which
from a practical point of view means that the TUN device was created with the
same UID/GID as the QEMU instance. If you want TUN device separation between
QEMU instances using DAC you need to run each QEMU instance with a different
UID/GID (which you should be doing anyway if you want DAC enforced general
separation).
I believe I've stated this point several times now and I don't feel you've
addressed it properly.
Look at how it works at the moment:
a priveledged libvirt server calls tun_set_iff
and passes the fd to qemu which is not priveledged.
The result is isolation between qemu instances without
need to create uid per qemu instance.
How do we create multiple queues? It makes sense to
follow this model and pass in fds for individual queues.
However they need to be disabled initially
so libvirt can not do tun_set_queue for us.
When qemu later calls tun_set_queue it will fail which means we
can't utilize multiqueue.
My solution is an unpriveledged variant
of tun_set_queue that only enables/disables
a queue without attach/detach.
--
paul moore
security and virtualization @ redhat
From: Eric Paris <hidden> Date: 2012-12-10 18:42:12
Let me abstract a little here Paul. Lets say user A starts an
unclassified process and a top secret process. SELinux policy darn
well better be able to enforce that they can not attach to the same
tun.
Am I missing something here?
On Mon, Dec 10, 2012 at 12:50 PM, Michael S. Tsirkin [off-list ref] wrote:
On Mon, Dec 10, 2012 at 12:33:49PM -0500, Paul Moore wrote:
quoted
On Monday, December 10, 2012 07:26:56 PM Michael S. Tsirkin wrote:
quoted
On Mon, Dec 10, 2012 at 12:04:35PM -0500, Paul Moore wrote:
quoted
On Friday, December 07, 2012 02:25:16 PM Michael S. Tsirkin wrote:
quoted
On Thu, Dec 06, 2012 at 04:09:51PM -0500, Paul Moore wrote:
quoted
On Thursday, December 06, 2012 10:57:16 PM Michael S. Tsirkin wrote:
quoted
On Thu, Dec 06, 2012 at 11:56:45AM -0500, Paul Moore wrote:
quoted
The SETQUEUE/tun_socket:create_queue permissions do not yet exist
in any released SELinux policy as we are just now adding them with
this patchset. With current policies loaded into a kernel with
this patchset applied the SETQUEUE/tun_socket:create_queue
permission would be treated according to the policy's unknown
permission setting.
OK I think we need to rethink what we are doing here: what you sent
addresses the problem as stated but I think we mis-stated it. Let
me try to restate the problem: it is not just selinux problem. Let's
assume qemu wants to use tun, I (libvirt) don't want to run it as
root.
1. TUNSETIFF: I can open tun, attach an fd and pass it to qemu.
Now, qemu does not invoke TUNSETIFF so it can run without
kernel priveledges.
Correct me if I'm wrong, but I believe libvirt does this while running
as root. Assuming that is the case, why not simply setuid()/setgid()
to the same credentials as the QEMU instance before creating the TUN
device? You can always (re)configure the device afterwards while
running as root/CAP_NET_ADMIN.
We want isolation between qemu instances.
Understood, I agree.
Achieving separation via SELinux is easily done, with libvirt/sVirt
already doing this for us automatically in most cases; the only thing we
will want to do is make sure the SELinux policy is aware of the new
permission.
Achieving separation via DAC should also be easily done, simply run each
QEMU instance with a separate UID and/or GID.
quoted
Giving qemu right to open tun and SETIFF would give it rights
to access any tun device.
I'm quickly looked at tun_chr_open() again and I don't see any special
rights/privileges required, the same for tun_chr_ioctl() and
__tun_chr_ioctl(). Looking at tun_set_queue() I see we call
tun_not_capable() which does a simple DAC check; it must have the same
UID/GID or have CAP_NET_ADMIN.
I'm having a hard time seeing the problem you are describing; help me
understand.
The issue is guest controls the number of queues in use.
So qemu would be required to be allowed to call tun_set_queue.
If we allow this we have a problem as one qemu will be
able to access any tun.
QEMU can call tun_set_queue() as long as it satisfies tun_not_capable(), which
from a practical point of view means that the TUN device was created with the
same UID/GID as the QEMU instance. If you want TUN device separation between
QEMU instances using DAC you need to run each QEMU instance with a different
UID/GID (which you should be doing anyway if you want DAC enforced general
separation).
I believe I've stated this point several times now and I don't feel you've
addressed it properly.
Look at how it works at the moment:
a priveledged libvirt server calls tun_set_iff
and passes the fd to qemu which is not priveledged.
The result is isolation between qemu instances without
need to create uid per qemu instance.
How do we create multiple queues? It makes sense to
follow this model and pass in fds for individual queues.
However they need to be disabled initially
so libvirt can not do tun_set_queue for us.
When qemu later calls tun_set_queue it will fail which means we
can't utilize multiqueue.
My solution is an unpriveledged variant
of tun_set_queue that only enables/disables
a queue without attach/detach.
quoted
--
paul moore
security and virtualization @ redhat
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Paul Moore <hidden> Date: 2012-12-10 22:21:44
On Monday, December 10, 2012 01:42:12 PM Eric Paris wrote:
Let me abstract a little here Paul. Lets say user A starts an
unclassified process and a top secret process. SELinux policy darn
well better be able to enforce that they can not attach to the same
tun.
Am I missing something here?
Relax, all the SELinux enforced separation still exists, and works. We're
just fixing the LSM/SELinux stuff that was broken with the multiqueue addition
and adding a new SELinux permission to control access to the new queue
command.
What we are currently discussing is DAC only. While Michael have different
opinions on how to solve the DAC issues, we agree that SELinux works
correctly.
--
paul moore
security and virtualization @ redhat
From: Paul Moore <hidden> Date: 2012-12-10 22:43:49
On Monday, December 10, 2012 07:50:35 PM Michael S. Tsirkin wrote:
On Mon, Dec 10, 2012 at 12:33:49PM -0500, Paul Moore wrote:
quoted
On Monday, December 10, 2012 07:26:56 PM Michael S. Tsirkin wrote:
quoted
On Mon, Dec 10, 2012 at 12:04:35PM -0500, Paul Moore wrote:
quoted
On Friday, December 07, 2012 02:25:16 PM Michael S. Tsirkin wrote:
quoted
On Thu, Dec 06, 2012 at 04:09:51PM -0500, Paul Moore wrote:
quoted
On Thursday, December 06, 2012 10:57:16 PM Michael S. Tsirkin
wrote:
quoted
quoted
quoted
quoted
quoted
quoted
On Thu, Dec 06, 2012 at 11:56:45AM -0500, Paul Moore wrote:
quoted
The SETQUEUE/tun_socket:create_queue permissions do not yet
exist
in any released SELinux policy as we are just now adding them
with
this patchset. With current policies loaded into a kernel with
this patchset applied the SETQUEUE/tun_socket:create_queue
permission would be treated according to the policy's unknown
permission setting.
OK I think we need to rethink what we are doing here: what you
sent
addresses the problem as stated but I think we mis-stated it.
Let
me try to restate the problem: it is not just selinux problem.
Let's
assume qemu wants to use tun, I (libvirt) don't want to run it
as
root.
1. TUNSETIFF: I can open tun, attach an fd and pass it to qemu.
Now, qemu does not invoke TUNSETIFF so it can run without
kernel priveledges.
Correct me if I'm wrong, but I believe libvirt does this while
running
as root. Assuming that is the case, why not simply
setuid()/setgid()
to the same credentials as the QEMU instance before creating the
TUN
device? You can always (re)configure the device afterwards while
running as root/CAP_NET_ADMIN.
We want isolation between qemu instances.
Understood, I agree.
Achieving separation via SELinux is easily done, with libvirt/sVirt
already doing this for us automatically in most cases; the only thing
we
will want to do is make sure the SELinux policy is aware of the new
permission.
Achieving separation via DAC should also be easily done, simply run
each
QEMU instance with a separate UID and/or GID.
quoted
Giving qemu right to open tun and SETIFF would give it rights
to access any tun device.
I'm quickly looked at tun_chr_open() again and I don't see any special
rights/privileges required, the same for tun_chr_ioctl() and
__tun_chr_ioctl(). Looking at tun_set_queue() I see we call
tun_not_capable() which does a simple DAC check; it must have the same
UID/GID or have CAP_NET_ADMIN.
I'm having a hard time seeing the problem you are describing; help me
understand.
The issue is guest controls the number of queues in use.
So qemu would be required to be allowed to call tun_set_queue.
If we allow this we have a problem as one qemu will be
able to access any tun.
QEMU can call tun_set_queue() as long as it satisfies tun_not_capable(),
which from a practical point of view means that the TUN device was
created with the same UID/GID as the QEMU instance. If you want TUN
device separation between QEMU instances using DAC you need to run each
QEMU instance with a different UID/GID (which you should be doing anyway
if you want DAC enforced general separation).
I believe I've stated this point several times now and I don't feel you've
addressed it properly.
Look at how it works at the moment:
a priveledged libvirt server calls tun_set_iff
and passes the fd to qemu which is not priveledged.
The result is isolation between qemu instances without
need to create uid per qemu instance.
Okay, good. That is my understanding.
How do we create multiple queues? It makes sense to
follow this model and pass in fds for individual queues.
Okay.
However they need to be disabled initially
so libvirt can not do tun_set_queue for us.
Unrelated question: why do the queues need to be disabled initially? Is this
to prevent traffic from being queued up? Some other reason? I'm just curious
as to the reason ...
When qemu later calls tun_set_queue it will fail which means we
can't utilize multiqueue.
I still don't understand why in the multiqueue case libvirt doesn't just
change it's effective UID/GID when creating the TUN device, or just use the
TUNSETOWNER/TUNSETGROUP commands. This would solve the problem you describe
above and - at least to me - seems like a better solution conceptually.
Help me understand why you believe that will not work.
Do you not want to give ownership of the TUN device to QEMU? That would be
the only reason I can think of, but all of your comments that I can recall
have been about isolation between QEMU instances and not access control
between a QEMU instance and its assigned TUN device.
My solution is an unpriveledged variant
of tun_set_queue that only enables/disables
a queue without attach/detach.
--
paul moore
security and virtualization @ redhat
From: Jason Wang <hidden> Date: 2012-12-11 06:41:02
On Monday, December 10, 2012 05:43:49 PM Paul Moore wrote:
On Monday, December 10, 2012 07:50:35 PM Michael S. Tsirkin wrote:
quoted
On Mon, Dec 10, 2012 at 12:33:49PM -0500, Paul Moore wrote:
quoted
On Monday, December 10, 2012 07:26:56 PM Michael S. Tsirkin wrote:
quoted
On Mon, Dec 10, 2012 at 12:04:35PM -0500, Paul Moore wrote:
quoted
On Friday, December 07, 2012 02:25:16 PM Michael S. Tsirkin wrote:
quoted
On Thu, Dec 06, 2012 at 04:09:51PM -0500, Paul Moore wrote:
quoted
On Thursday, December 06, 2012 10:57:16 PM Michael S. Tsirkin
wrote:
quoted
quoted
quoted
quoted
quoted
quoted
quoted
On Thu, Dec 06, 2012 at 11:56:45AM -0500, Paul Moore wrote:
quoted
The SETQUEUE/tun_socket:create_queue permissions do not yet
exist
in any released SELinux policy as we are just now adding
them
with
this patchset. With current policies loaded into a kernel
with
this patchset applied the SETQUEUE/tun_socket:create_queue
permission would be treated according to the policy's
unknown
permission setting.
OK I think we need to rethink what we are doing here: what you
sent
addresses the problem as stated but I think we mis-stated it.
Let
me try to restate the problem: it is not just selinux problem.
Let's
assume qemu wants to use tun, I (libvirt) don't want to run it
as
root.
1. TUNSETIFF: I can open tun, attach an fd and pass it to
qemu.
Now, qemu does not invoke TUNSETIFF so it can run without
kernel priveledges.
Correct me if I'm wrong, but I believe libvirt does this while
running
as root. Assuming that is the case, why not simply
setuid()/setgid()
to the same credentials as the QEMU instance before creating the
TUN
device? You can always (re)configure the device afterwards while
running as root/CAP_NET_ADMIN.
We want isolation between qemu instances.
Understood, I agree.
Achieving separation via SELinux is easily done, with libvirt/sVirt
already doing this for us automatically in most cases; the only
thing
we
will want to do is make sure the SELinux policy is aware of the new
permission.
Achieving separation via DAC should also be easily done, simply run
each
QEMU instance with a separate UID and/or GID.
quoted
Giving qemu right to open tun and SETIFF would give it rights
to access any tun device.
I'm quickly looked at tun_chr_open() again and I don't see any
special
rights/privileges required, the same for tun_chr_ioctl() and
__tun_chr_ioctl(). Looking at tun_set_queue() I see we call
tun_not_capable() which does a simple DAC check; it must have the
same
UID/GID or have CAP_NET_ADMIN.
I'm having a hard time seeing the problem you are describing; help
me
understand.
The issue is guest controls the number of queues in use.
So qemu would be required to be allowed to call tun_set_queue.
If we allow this we have a problem as one qemu will be
able to access any tun.
QEMU can call tun_set_queue() as long as it satisfies tun_not_capable(),
which from a practical point of view means that the TUN device was
created with the same UID/GID as the QEMU instance. If you want TUN
device separation between QEMU instances using DAC you need to run each
QEMU instance with a different UID/GID (which you should be doing anyway
if you want DAC enforced general separation).
I believe I've stated this point several times now and I don't feel
you've
addressed it properly.
Look at how it works at the moment:
a priveledged libvirt server calls tun_set_iff
and passes the fd to qemu which is not priveledged.
The result is isolation between qemu instances without
need to create uid per qemu instance.
Okay, good. That is my understanding.
quoted
How do we create multiple queues? It makes sense to
follow this model and pass in fds for individual queues.
Okay.
quoted
However they need to be disabled initially
so libvirt can not do tun_set_queue for us.
Unrelated question: why do the queues need to be disabled initially? Is
this to prevent traffic from being queued up? Some other reason? I'm jus
curious as to the reason ...
Only one queue is used by default, so queues other than 0 should be disabled
after creating by either libvirt or qemu. There're several choices:
A. libvirt only calls TUNSETIFF, and passing this fd to qemu. Qemu creates the
rest of the queues through TUNSETQUEUE, and also disable them by default
B. libvirt calls TUNSETIFF and creates queues through TUNSETQUEUE, then it
passes all file descriptors to qemu. Qemu disables queues other than 0 by
default.
C. libvirt call TUNSETIFF, TUNSETQUEUE to create queues and disable all queues
other than queue 0. Then it can pass all the file descriptors to qemu.
Since qemu is not priveledged, method A is not applicable, since creating
queues needs CAT_NET_ADMIN. Either B or C is ok if we add an extra flags to
disable/enable the queue.
quoted
When qemu later calls tun_set_queue it will fail which means we
can't utilize multiqueue.
I still don't understand why in the multiqueue case libvirt doesn't just
change it's effective UID/GID when creating the TUN device, or just use the
TUNSETOWNER/TUNSETGROUP commands. This would solve the problem you describe
above and - at least to me - seems like a better solution conceptually.
I think it make sense to do this. Have a quick glance on libvirt code, looks
like it does not call TUNSETOWNER/TUNSETGROUP. Maybe libvirt guys (cc'ed) can
answer this question.
Help me understand why you believe that will not work.
Do you not want to give ownership of the TUN device to QEMU? That would be
the only reason I can think of, but all of your comments that I can recall
have been about isolation between QEMU instances and not access control
between a QEMU instance and its assigned TUN device.
quoted
My solution is an unpriveledged variant
of tun_set_queue that only enables/disables
a queue without attach/detach.
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2012-12-12 09:07:14
On Mon, Dec 10, 2012 at 05:43:49PM -0500, Paul Moore wrote:
On Monday, December 10, 2012 07:50:35 PM Michael S. Tsirkin wrote:
quoted
On Mon, Dec 10, 2012 at 12:33:49PM -0500, Paul Moore wrote:
quoted
On Monday, December 10, 2012 07:26:56 PM Michael S. Tsirkin wrote:
quoted
On Mon, Dec 10, 2012 at 12:04:35PM -0500, Paul Moore wrote:
quoted
On Friday, December 07, 2012 02:25:16 PM Michael S. Tsirkin wrote:
quoted
On Thu, Dec 06, 2012 at 04:09:51PM -0500, Paul Moore wrote:
quoted
On Thursday, December 06, 2012 10:57:16 PM Michael S. Tsirkin
wrote:
quoted
quoted
quoted
quoted
quoted
quoted
quoted
On Thu, Dec 06, 2012 at 11:56:45AM -0500, Paul Moore wrote:
quoted
The SETQUEUE/tun_socket:create_queue permissions do not yet
exist
in any released SELinux policy as we are just now adding them
with
this patchset. With current policies loaded into a kernel with
this patchset applied the SETQUEUE/tun_socket:create_queue
permission would be treated according to the policy's unknown
permission setting.
OK I think we need to rethink what we are doing here: what you
sent
addresses the problem as stated but I think we mis-stated it.
Let
me try to restate the problem: it is not just selinux problem.
Let's
assume qemu wants to use tun, I (libvirt) don't want to run it
as
root.
1. TUNSETIFF: I can open tun, attach an fd and pass it to qemu.
Now, qemu does not invoke TUNSETIFF so it can run without
kernel priveledges.
Correct me if I'm wrong, but I believe libvirt does this while
running
as root. Assuming that is the case, why not simply
setuid()/setgid()
to the same credentials as the QEMU instance before creating the
TUN
device? You can always (re)configure the device afterwards while
running as root/CAP_NET_ADMIN.
We want isolation between qemu instances.
Understood, I agree.
Achieving separation via SELinux is easily done, with libvirt/sVirt
already doing this for us automatically in most cases; the only thing
we
will want to do is make sure the SELinux policy is aware of the new
permission.
Achieving separation via DAC should also be easily done, simply run
each
QEMU instance with a separate UID and/or GID.
quoted
Giving qemu right to open tun and SETIFF would give it rights
to access any tun device.
I'm quickly looked at tun_chr_open() again and I don't see any special
rights/privileges required, the same for tun_chr_ioctl() and
__tun_chr_ioctl(). Looking at tun_set_queue() I see we call
tun_not_capable() which does a simple DAC check; it must have the same
UID/GID or have CAP_NET_ADMIN.
I'm having a hard time seeing the problem you are describing; help me
understand.
The issue is guest controls the number of queues in use.
So qemu would be required to be allowed to call tun_set_queue.
If we allow this we have a problem as one qemu will be
able to access any tun.
QEMU can call tun_set_queue() as long as it satisfies tun_not_capable(),
which from a practical point of view means that the TUN device was
created with the same UID/GID as the QEMU instance. If you want TUN
device separation between QEMU instances using DAC you need to run each
QEMU instance with a different UID/GID (which you should be doing anyway
if you want DAC enforced general separation).
I believe I've stated this point several times now and I don't feel you've
addressed it properly.
Look at how it works at the moment:
a priveledged libvirt server calls tun_set_iff
and passes the fd to qemu which is not priveledged.
The result is isolation between qemu instances without
need to create uid per qemu instance.
Okay, good. That is my understanding.
quoted
How do we create multiple queues? It makes sense to
follow this model and pass in fds for individual queues.
Okay.
quoted
However they need to be disabled initially
so libvirt can not do tun_set_queue for us.
Unrelated question: why do the queues need to be disabled initially? Is this
to prevent traffic from being queued up? Some other reason? I'm just curious
as to the reason ...
Yes.
Basically because old guests only use a single queue.
If a guest comes along and declares multiqueue support
we can queue up traffic on new queues but if we
do this with a legacy guest it will not be able to
consume it.
quoted
can't utilize multiqueue.
I still don't understand why in the multiqueue case libvirt doesn't just
change it's effective UID/GID when creating the TUN device, or just use the
TUNSETOWNER/TUNSETGROUP commands. This would solve the problem you describe
above and - at least to me - seems like a better solution conceptually.
Help me understand why you believe that will not work.
Do you not want to give ownership of the TUN device to QEMU? That would be
the only reason I can think of, but all of your comments that I can recall
have been about isolation between QEMU instances and not access control
between a QEMU instance and its assigned TUN device.
I think I might have confused things more than clarified them.
Let me comment on specific lines in patch that worry me
that will make it clear I hope.
quoted
My solution is an unpriveledged variant
of tun_set_queue that only enables/disables
a queue without attach/detach.
--
paul moore
security and virtualization @ redhat
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2012-12-12 09:22:36
On Wed, Dec 05, 2012 at 03:26:19PM -0500, Paul Moore wrote:
quoted hunk
This patch corrects some problems with LSM/SELinux that were introduced
with the multiqueue patchset. The problem stems from the fact that the
multiqueue work changed the relationship between the tun device and its
associated socket; before the socket persisted for the life of the
device, however after the multiqueue changes the socket only persisted
for the life of the userspace connection (fd open). For non-persistent
devices this is not an issue, but for persistent devices this can cause
the tun device to lose its SELinux label.
We correct this problem by adding an opaque LSM security blob to the
tun device struct which allows us to have the LSM security state, e.g.
SELinux labeling information, persist for the lifetime of the tun
device. In the process we tweak the LSM hooks to work with this new
approach to TUN device/socket labeling and introduce a new LSM hook,
security_tun_dev_create_queue(), to approve requests to create a new
TUN queue via TUNSETQUEUE.
The SELinux code has been adjusted to match the new LSM hooks, the
other LSMs do not make use of the LSM TUN controls. This patch makes
use of the recently added "tun_socket:create_queue" permission to
restrict access to the TUNSETQUEUE operation. On older SELinux
policies which do not define the "tun_socket:create_queue" permission
the access control decision for TUNSETQUEUE will be handled according
to the SELinux policy's unknown permission setting.
Signed-off-by: Paul Moore <redacted>
---
drivers/net/tun.c | 26 +++++++++++++---
include/linux/security.h | 59 +++++++++++++++++++++++++++++--------
security/capability.c | 24 +++++++++++++--
security/security.c | 28 ++++++++++++++----
security/selinux/hooks.c | 50 ++++++++++++++++++++++++-------
security/selinux/include/objsec.h | 4 +++
6 files changed, 153 insertions(+), 38 deletions(-)
This hook triggers with both set_queue and set_iff,
and it also seems to trigger when attaching to a
persistent device and when creating a new one. But I
believe we might want to be able to allow one but not the other.
For example:
- we might want to allow qemu to do set_queue but not set_iff
- we might want to configure presistent devices and
prevent a user from adding new ones
I worry that removing a hook hurt users that use it in their
ecurity policy.
quoted hunk
+ * @tun_dev_create_queue:
+ * Check permissions prior to creating a new TUN device queue.
+ * @security pointer to the TUN device's security structure.
* @tun_dev_attach:
- * Check permissions prior to attaching to a persistent TUN device. This
- * hook can also be used by the module to update any security state
+ * This hook can be used by the module to update any security state
* associated with the TUN device's sock structure.
* @sk contains the existing sock structure.
+ * @security pointer to the TUN device's security structure.
+ * @tun_dev_open:
+ * This hook can be used by the module to update any security state
+ * associated with the TUN device's security structure.
+ * @security pointer to the TUN devices's security structure.
*
* Security hooks for XFRM operations.
*
@@ -1613,9 +1625,12 @@ struct security_operations { void (*secmark_refcount_inc) (void); void (*secmark_refcount_dec) (void); void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);- int (*tun_dev_create)(void);- void (*tun_dev_post_create)(struct sock *sk);- int (*tun_dev_attach)(struct sock *sk);+ int (*tun_dev_alloc_security) (void **security);+ void (*tun_dev_free_security) (void *security);+ int (*tun_dev_create) (void);+ int (*tun_dev_create_queue) (void *security);+ int (*tun_dev_attach) (struct sock *sk, void *security);+ int (*tun_dev_open) (void *security); #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -4414,8 +4432,17 @@ static int selinux_tun_dev_create(void)NULL);}-staticvoidselinux_tun_dev_post_create(structsock*sk)+staticintselinux_tun_dev_create_queue(void*security){+structtun_security_struct*tunsec=security;++returnavc_has_perm(current_sid(),tunsec->sid,SECCLASS_TUN_SOCKET,+TUN_SOCKET__CREATE_QUEUE,NULL);+}++staticintselinux_tun_dev_attach(structsock*sk,void*security)+{+structtun_security_struct*tunsec=security;structsk_security_struct*sksec=sk->sk_security;/* we don't currently perform any NetLabel based labeling here and it
@@ -4425,20 +4452,19 @@ static void selinux_tun_dev_post_create(struct sock *sk)*causeconfusiontotheTUNuserthathadnoideanetworklabeling*protocolswerebeingused*/-/* see the comments in selinux_tun_dev_create() about why we don't use-*thesockcreateSIDhere*/--sksec->sid=current_sid();+sksec->sid=tunsec->sid;sksec->sclass=SECCLASS_TUN_SOCKET;++return0;}-staticintselinux_tun_dev_attach(structsock*sk)+staticintselinux_tun_dev_open(void*security){-structsk_security_struct*sksec=sk->sk_security;+structtun_security_struct*tunsec=security;u32sid=current_sid();interr;-err=avc_has_perm(sid,sksec->sid,SECCLASS_TUN_SOCKET,+err=avc_has_perm(sid,tunsec->sid,SECCLASS_TUN_SOCKET,TUN_SOCKET__RELABELFROM,NULL);if(err)returnerr;
@@ -4446,8 +4472,7 @@ static int selinux_tun_dev_attach(struct sock *sk)TUN_SOCKET__RELABELTO,NULL);if(err)returnerr;--sksec->sid=sid;+tunsec->sid=sid;return0;}
@@ -110,6 +110,10 @@ struct sk_security_struct {u16sclass;/* sock security class */};+structtun_security_struct{+u32sid;/* SID for the tun device sockets */+};+structkey_security_struct{u32sid;/* SID of key */};
From: Paul Moore <hidden> Date: 2012-12-12 18:49:35
On Wednesday, December 12, 2012 11:22:36 AM Michael S. Tsirkin wrote:
On Wed, Dec 05, 2012 at 03:26:19PM -0500, Paul Moore wrote:
quoted
This patch corrects some problems with LSM/SELinux that were introduced
with the multiqueue patchset. The problem stems from the fact that the
multiqueue work changed the relationship between the tun device and its
associated socket; before the socket persisted for the life of the
device, however after the multiqueue changes the socket only persisted
for the life of the userspace connection (fd open). For non-persistent
devices this is not an issue, but for persistent devices this can cause
the tun device to lose its SELinux label.
We correct this problem by adding an opaque LSM security blob to the
tun device struct which allows us to have the LSM security state, e.g.
SELinux labeling information, persist for the lifetime of the tun
device. In the process we tweak the LSM hooks to work with this new
approach to TUN device/socket labeling and introduce a new LSM hook,
security_tun_dev_create_queue(), to approve requests to create a new
TUN queue via TUNSETQUEUE.
The SELinux code has been adjusted to match the new LSM hooks, the
other LSMs do not make use of the LSM TUN controls. This patch makes
use of the recently added "tun_socket:create_queue" permission to
restrict access to the TUNSETQUEUE operation. On older SELinux
policies which do not define the "tun_socket:create_queue" permission
the access control decision for TUNSETQUEUE will be handled according
to the SELinux policy's unknown permission setting.
...
quoted
@@ -465,6 +466,10 @@ static int tun_attach(struct tun_struct *tun, struct
This hook triggers with both set_queue and set_iff,
and it also seems to trigger when attaching to a
persistent device and when creating a new one. But I
believe we might want to be able to allow one but not the other.
For example:
- we might want to allow qemu to do set_queue but not set_iff
- we might want to configure presistent devices and
prevent a user from adding new ones
Please look at the rest of the patch and see what the hook actually does. It
does not perform any access control under SELinux, all it does is ensure that
the socket is labeled based on the associated TUN device.
quoted
- * @tun_dev_post_create:
- * This hook allows a module to update or allocate a per-socket security
- * structure.
- * @sk contains the newly created sock structure.
I worry that removing a hook hurt users that use it in their
security policy.
We need to change the hooks because there was a significant change to the
implementation of a TUN device.
However, even when changing the LSM hooks, we have preserved the SELinux
access controls for standard, e.g. single queue, TUN devices such that
existing SELinux policies will work for existing TUN users. The new SELinux
access control we added only comes into play when TUN users want to enable
multiple queues.
--
paul moore
security and virtualization @ redhat