* Re: [PATCH 5/5] c/r: Add AF_UNIX support (v7)
From: Dan Smith @ 2009-08-04 22:47 UTC (permalink / raw)
To: Serge E. Hallyn; +Cc: containers, Alexey Dobriyan, netdev
In-Reply-To: <20090804223141.GA14254@us.ibm.com>
SH> why only free iov_base if ret!=0?
Because I was diagnosing a crash that only seemed to happen when I
free()'d the buffer after it was used by sendmsg() and I forgot to
remove this :(
>> + a->sk_peercred.pid = task_tgid_vnr(current);
>> + a->sk_peercred.uid = ctx->realcred->uid;
SH> I don't know how much it matters, but of course root could be
SH> restarting a set of tasks owned by several non-root uids, and the
SH> peercred.uid's might need to be something other than
ctx-> realcred->uid. Or not?
Oh, so you're suggesting I use ctx->ecred instead? I didn't actually
notice the double declaration in the ckpt_ctx, but I guess that would
be better.
--
Dan Smith
IBM Linux Technology Center
email: danms@us.ibm.com
^ permalink raw reply
* Re: [PATCH 5/5] c/r: Add AF_UNIX support (v7)
From: Serge E. Hallyn @ 2009-08-04 22:31 UTC (permalink / raw)
To: Dan Smith; +Cc: containers, Alexey Dobriyan, netdev
In-Reply-To: <1249331463-11887-6-git-send-email-danms@us.ibm.com>
Quoting Dan Smith (danms@us.ibm.com):
> +static int sock_read_buffer_sendmsg(struct ckpt_ctx *ctx, struct sock *sock)
> +{
> + struct msghdr msg;
> + struct kvec kvec;
> + int ret = 0;
> + int len;
> +
> + memset(&msg, 0, sizeof(msg));
> +
> + len = _ckpt_read_obj_type(ctx, NULL, 0, CKPT_HDR_SOCKET_BUFFER);
> + if (len < 0)
> + return len;
> +
> + if (len > SKB_MAX_ALLOC) {
> + ckpt_debug("Socket buffer too big (%i > %lu)",
> + len, SKB_MAX_ALLOC);
> + return -ENOSPC;
> + }
> +
> + kvec.iov_len = len;
> + kvec.iov_base = kmalloc(len, GFP_KERNEL);
> + if (!kvec.iov_base)
> + return -ENOMEM;
> +
> + ret = ckpt_kread(ctx, kvec.iov_base, len);
> + if (ret < 0)
> + goto out;
> +
> + ret = kernel_sendmsg(sock->sk_socket, &msg, &kvec, 1, len);
> + ckpt_debug("kernel_sendmsg(%i): %i\n", len, ret);
> + if ((ret > 0) && (ret != len))
> + ret = -ENOMEM;
> + out:
> + if (ret)
why only free iov_base if ret!=0?
> + kfree(kvec.iov_base);
> +
> + return ret;
> +}
> +
> +static struct ckpt_hdr_socket_queue *sock_read_buffer_hdr(struct ckpt_ctx *ctx,
> + uint32_t *bufsize)
> +{
> + struct ckpt_hdr_socket_queue *h;
> + int err = 0;
> +
> + h = ckpt_read_obj_type(ctx, sizeof(*h), CKPT_HDR_SOCKET_QUEUE);
> + if (IS_ERR(h))
> + return h;
> +
> + if (!bufsize) {
> + if (h->total_bytes != 0) {
> + ckpt_debug("Expected empty buffer, got %u\n",
> + h->total_bytes);
> + err = -EINVAL;
> + }
> + } else if (h->total_bytes > *bufsize) {
> + /* NB: We let CAP_NET_ADMIN override the system buffer limit
> + * as setsockopt() does
> + */
> + if (capable(CAP_NET_ADMIN))
> + *bufsize = h->total_bytes;
> + else {
> + ckpt_debug("Buffer total %u exceeds limit %u\n",
> + h->total_bytes, *bufsize);
> + err = -EINVAL;
> + }
> + }
> +
> + if (err) {
> + ckpt_hdr_put(ctx, h);
> + return ERR_PTR(err);
> + } else
> + return h;
> +}
> +
> +static int sock_unix_read_buffers(struct ckpt_ctx *ctx,
> + struct sock *sock,
> + uint32_t *bufsize)
> +{
> + uint8_t sock_shutdown;
> + struct ckpt_hdr_socket_queue *h;
> + int ret = 0;
> + int i;
> +
> + h = sock_read_buffer_hdr(ctx, bufsize);
> + if (IS_ERR(h))
> + return PTR_ERR(h);
> +
> + /* If peer is shutdown, unshutdown it for this process */
> + sock_shutdown = sock->sk_shutdown;
> + sock->sk_shutdown &= ~SHUTDOWN_MASK;
> +
> + for (i = 0; i < h->skb_count; i++) {
> + ret = sock_read_buffer_sendmsg(ctx, sock);
> + ckpt_debug("read_buffer_sendmsg(%i): %i\n", i, ret);
> + if (ret < 0)
> + break;
> +
> + if (ret > h->total_bytes) {
> + ckpt_debug("Buffers exceeded claim");
> + ret = -EINVAL;
> + break;
> + }
> +
> + h->total_bytes -= ret;
> + ret = 0;
> + }
> +
> + sock->sk_shutdown = sock_shutdown;
> + ckpt_hdr_put(ctx, h);
> +
> + return ret;
> +}
> +
> +static struct unix_address *sock_unix_makeaddr(struct sockaddr_un *sun_addr,
> + unsigned len)
> +{
> + struct unix_address *addr;
> +
> + if (len > sizeof(struct sockaddr_un))
> + return ERR_PTR(-EINVAL);
> +
> + addr = kmalloc(sizeof(*addr) + len, GFP_KERNEL);
> + if (!addr)
> + return ERR_PTR(-ENOMEM);
> +
> + memcpy(addr->name, sun_addr, len);
> + addr->len = len;
> + atomic_set(&addr->refcnt, 1);
> +
> + return addr;
> +}
> +
> +static int sock_unix_join(struct ckpt_ctx *ctx,
> + struct sock *a,
> + struct sock *b,
> + struct ckpt_hdr_socket_unix *un)
> +{
> + struct unix_address *addr = NULL;
> +
> + /* FIXME: Do we need to call some security hooks here? */
> +
> + sock_hold(a);
> + sock_hold(b);
> +
> + unix_sk(a)->peer = b;
> + unix_sk(b)->peer = a;
> +
> + a->sk_peercred.pid = task_tgid_vnr(current);
> + a->sk_peercred.uid = ctx->realcred->uid;
I don't know how much it matters, but of course root could
be restarting a set of tasks owned by several non-root uids,
and the peercred.uid's might need to be something other than
ctx->realcred->uid. Or not?
> + a->sk_peercred.gid = ctx->realcred->gid;
> +
> + b->sk_peercred.pid = a->sk_peercred.pid;
> + b->sk_peercred.uid = a->sk_peercred.uid;
> + b->sk_peercred.gid = a->sk_peercred.gid;
> +
-serge
^ permalink raw reply
* Re: [PATCH 5/5] c/r: Add AF_UNIX support (v7)
From: Dan Smith @ 2009-08-04 22:24 UTC (permalink / raw)
To: Serge E. Hallyn; +Cc: containers, Alexey Dobriyan, netdev
In-Reply-To: <20090804211742.GC13499@us.ibm.com>
SH> I don't understand. Which pid?
I meant the socket's peercred, which includes the pid of the process
that opened it, but that clearly won't work... :)
--
Dan Smith
IBM Linux Technology Center
email: danms@us.ibm.com
^ permalink raw reply
* [PATCH 7/7 v1] initdev:kernel:Await block device discovery
From: David VomLehn @ 2009-08-04 22:15 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, linux-usb, greg, linux-scsi, netdev, arjan
Use the initdev infrastructure to wait for a root device to become available.
This should make most uses of the kernel rootwait parameter unnecessary. The
only time it should be necessary is when the root device might not be attached
at boot time.
Signed-off-by: David VomLehn <dvomlehn@cisco>
---
init/do_mounts.c | 29 +++++++++++++++++++++++++----
1 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/init/do_mounts.c b/init/do_mounts.c
index dd7ee5f..36a92ae 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -358,6 +358,18 @@ void __init mount_root(void)
#endif
}
+/**
+ * root_present - determine whether the root device is available yet
+ *
+ * Returns true if the root device is available, false if not. The check to
+ * see if the root device is available is done by check to see whether it
+ * has been assigned a major/minor device number.
+ */
+static bool root_present(void)
+{
+ return name_to_dev_t(saved_root_name) != 0;
+}
+
/*
* Prepare the namespace - decide what/where to mount, load ramdisks, etc.
*/
@@ -398,12 +410,21 @@ void __init prepare_namespace(void)
goto out;
/* wait for any asynchronous scanning to complete */
- if ((ROOT_DEV == 0) && root_wait) {
+ if (ROOT_DEV == 0) {
printk(KERN_INFO "Waiting for root device %s...\n",
saved_root_name);
- while (driver_probe_done() != 0 ||
- (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
- msleep(100);
+ if (root_wait) {
+ while (driver_probe_done() != 0 ||
+ (ROOT_DEV = name_to_dev_t(saved_root_name)) ==
+ 0)
+ msleep(100);
+ }
+
+ else {
+ initdev_wait(INITDEV_BLOCK_TYPE, root_present);
+ ROOT_DEV = name_to_dev_t(saved_root_name);
+ }
+
async_synchronize_full();
}
^ permalink raw reply related
* [PATCH 6/7 v1] initdev:kernel:SCSI asynchronous block init device notification
From: David VomLehn @ 2009-08-04 22:15 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, linux-usb, greg, linux-scsi, netdev, arjan
In addition to the bus initdev synchronization, SCSI also starts asynchronous
threads with which we must synchronize.
Signed-off-by: David VomLehn <dvomlehn@cisco.com>
---
drivers/scsi/sd.c | 2 ++
fs/partitions/check.c | 1 +
2 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 5616cd7..394235d 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2005,6 +2005,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
sdp->removable ? "removable " : "");
+ initdev_probe_done(INITDEV_BLOCK_MASK);
}
/**
@@ -2090,6 +2091,7 @@ static int sd_probe(struct device *dev)
get_device(&sdp->sdev_gendev);
+ initdev_found(INITDEV_BLOCK_MASK);
async_schedule(sd_probe_async, sdkp);
return 0;
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index ea4e6cb..a0fa50c 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -512,6 +512,7 @@ exit:
while ((part = disk_part_iter_next(&piter)))
kobject_uevent(&part_to_dev(part)->kobj, KOBJ_ADD);
disk_part_iter_exit(&piter);
+ initdev_registered(INITDEV_BLOCK_TYPE);
}
int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
^ permalink raw reply related
* [PATCH 5/7 v4] initdev:kernel:USB and SCSI block init device notification
From: David VomLehn @ 2009-08-04 22:15 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, linux-usb, greg, linux-scsi, netdev, arjan
From: Alan Stern <stern@rowland.harvard.edu>
Add notification of device discovery for USB and SCSI block devices.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu
Signed-off-by: David VomLehn <dvomlehn@cisco.com>
---
drivers/scsi/scsi_scan.c | 2 ++
drivers/usb/storage/usb.c | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 6f51ca4..cb7b450 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1834,6 +1834,7 @@ static int do_scan_async(void *_data)
struct async_scan_data *data = _data;
do_scsi_scan_host(data->shost);
scsi_finish_async_scan(data);
+ initdev_probe_done(INITDEV_BLOCK_MASK);
return 0;
}
@@ -1855,6 +1856,7 @@ void scsi_scan_host(struct Scsi_Host *shost)
return;
}
+ initdev_found(INITDEV_BLOCK_MASK);
p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
if (IS_ERR(p))
do_scan_async(data);
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 8060b85..6a78278 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -837,6 +837,7 @@ static int usb_stor_scan_thread(void * __us)
/* Should we unbind if no devices were detected? */
}
+ initdev_probe_done(INITDEV_BLOCK_MASK);
complete_and_exit(&us->scanning_done, 0);
}
@@ -937,10 +938,12 @@ int usb_stor_probe2(struct us_data *us)
}
/* Start up the thread for delayed SCSI-device scanning */
+ initdev_found(INITDEV_BLOCK_MASK);
th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
if (IS_ERR(th)) {
printk(KERN_WARNING USB_STORAGE
"Unable to start the device-scanning thread\n");
+ initdev_probe_done(INITDEV_BLOCK_MASK);
complete(&us->scanning_done);
quiesce_and_remove_host(us);
result = PTR_ERR(th);
^ permalink raw reply related
* [PATCH 4/7 v3] initdev:kernel:Await network init device discovery
From: David VomLehn @ 2009-08-04 22:15 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
linux-usb-u79uwXL29TY76Z2rM5mHXA, greg-U8xfFu+wG4EAvxtiuMwx3w,
linux-scsi-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
arjan-wEGCiKHe2LqWVfeAwA7xHQ
Delay IP autoconfiguration until network boot devices have been initialized.
This depends on the boot device discovery code and on the asynchronous
function call infrastructure.
Signed-off-by: David VomLehn <dvomlehn-FYB4Gu1CFyUAvxtiuMwx3w@public.gmane.org>
---
net/core/dev.c | 2 +
net/ipv4/ipconfig.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 56 insertions(+), 1 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 308a7d0..2796764 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -93,6 +93,7 @@
#include <linux/ethtool.h>
#include <linux/notifier.h>
#include <linux/skbuff.h>
+#include <linux/device.h>
#include <net/net_namespace.h>
#include <net/sock.h>
#include <linux/rtnetlink.h>
@@ -4497,6 +4498,7 @@ int register_netdevice(struct net_device *dev)
dev->reg_state = NETREG_UNREGISTERED;
}
+ initdev_registered(INITDEV_NETDEV_TYPE);
out:
return ret;
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 90d22ae..3b1a381 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -53,6 +53,7 @@
#include <linux/root_dev.h>
#include <linux/delay.h>
#include <linux/nfs_fs.h>
+#include <linux/async.h>
#include <net/net_namespace.h>
#include <net/arp.h>
#include <net/ip.h>
@@ -182,12 +183,48 @@ struct ic_device {
static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */
static struct net_device *ic_dev __initdata = NULL; /* Selected device */
+/*
+ * Wait for required network devices to come up
+ * If the networking device name was specified on the kernel command line
+ * and that device is now registered, we have the device we want to configure
+ * and we return true. Otherwise, we return false. So, if no device was
+ * specified on the command line, we wait for all possible network devices to
+ * be initialized.
+ */
+static bool have_all_netdevs(void)
+{
+ struct net_device *dev;
+ bool result = false;
+
+ rtnl_lock();
+
+ for_each_netdev(&init_net, dev) {
+ if (dev->flags & IFF_LOOPBACK)
+ continue;
+
+ /* If a specific device name was specified and that name is
+ * registered, we have the device we need. */
+ if (user_dev_name[0] && !strcmp(dev->name, user_dev_name)) {
+ result = true;
+ break;
+ }
+ }
+
+ rtnl_unlock();
+
+ return result;
+
+}
+
static int __init ic_open_devs(void)
{
struct ic_device *d, **last;
struct net_device *dev;
unsigned short oflags;
+ /* Wait for networking devices */
+ initdev_wait(INITDEV_NETDEV_TYPE, have_all_netdevs);
+
last = &ic_first_dev;
rtnl_lock();
@@ -1263,6 +1300,7 @@ __be32 __init root_nfs_parse_addr(char *name)
/*
* IP Autoconfig dispatcher.
+ * Return zero on success, negative one on failure
*/
static int __init ip_auto_config(void)
@@ -1397,7 +1435,22 @@ static int __init ip_auto_config(void)
return 0;
}
-late_initcall(ip_auto_config);
+static void __init ip_auto_config_async(void *data, async_cookie_t cookie)
+{
+ ip_auto_config();
+}
+
+/*
+ * Start a thread to do IP autoconfiguration
+ */
+static int __init ip_auto_configurator(void)
+{
+ async_schedule(ip_auto_config_async, NULL);
+
+ return 0;
+}
+
+late_initcall(ip_auto_configurator);
/*
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 3/7 v6] initdev:kernel:Await console discovery
From: David VomLehn @ 2009-08-04 22:15 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, linux-usb, greg, linux-scsi, netdev, arjan
Wait for the console device to become available or for it to be determined
that no console is attached a boot time.
Signed-off-by: David VomLehn <dvomlehn@cisco.com>
---
drivers/accessibility/braille/braille_console.c | 2 +
kernel/printk.c | 29 ++++++++++++++++++++++-
2 files changed, 30 insertions(+), 1 deletions(-)
diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c
index d672cfe..6d1693f 100644
--- a/drivers/accessibility/braille/braille_console.c
+++ b/drivers/accessibility/braille/braille_console.c
@@ -378,6 +378,8 @@ int braille_register_console(struct console *console, int index,
braille_co = console;
register_keyboard_notifier(&keyboard_notifier_block);
register_vt_notifier(&vt_notifier_block);
+
+ initdev_registered(INITDEV_CONSOLE_TYPE);
return 0;
}
diff --git a/kernel/printk.c b/kernel/printk.c
index 5052b54..7cdc91c 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -33,6 +33,7 @@
#include <linux/bootmem.h>
#include <linux/syscalls.h>
#include <linux/kexec.h>
+#include <linux/device.h>
#include <asm/uaccess.h>
@@ -1075,8 +1076,10 @@ void console_unblank(void)
/*
* Return the console tty driver structure and its associated index
+ * @index: Pointer to the device index
+ * Returns NULL if no driver available, otherwise a pointer to the TTY driver.
*/
-struct tty_driver *console_device(int *index)
+struct tty_driver *_console_device(int *index)
{
struct console *c;
struct tty_driver *driver = NULL;
@@ -1094,6 +1097,29 @@ struct tty_driver *console_device(int *index)
}
/*
+ * Returns true if all specific consoles are registered, false otherwise
+ */
+static bool have_all_consoles(void)
+{
+ struct tty_driver *driver;
+ int index;
+
+ driver = _console_device(&index);
+
+ return driver != NULL;
+}
+
+struct tty_driver *console_device(int *index)
+{
+ struct tty_driver *driver;
+ initdev_wait(INITDEV_CONSOLE_TYPE, have_all_consoles);
+
+ driver = _console_device(index);
+
+ return driver;
+}
+
+/*
* Prevent further output on the passed console device so that (for example)
* serial drivers can disable console output before suspending a port, and can
* re-enable output afterwards.
@@ -1230,6 +1256,7 @@ void register_console(struct console *console)
spin_unlock_irqrestore(&logbuf_lock, flags);
}
release_console_sem();
+ initdev_registered(INITDEV_CONSOLE_TYPE);
}
EXPORT_SYMBOL(register_console);
^ permalink raw reply related
* [PATCH 2/7 v3] initdev:kernel:USB init device discovery notification
From: David VomLehn @ 2009-08-04 22:15 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, linux-usb, greg, linux-scsi, netdev, arjan
From: Alan Stern <stern@rowland.harvard.edu>
Use init device discovery infrastructure to provide notification of
availability of USB devices.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: David VomLehn <dvomlehn@cisco.com>
---
drivers/usb/core/hub.c | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index be86ae3..08baee0 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -37,6 +37,20 @@
#endif
#endif
+/* The mask of possible USB boot devices depends on what drivers and
+ * options have been configured into the kernel. There are too many
+ * USB network config options to list here, so just assume it is always
+ * possible to have a USB network device.
+ */
+static int usb_initdev_mask = 0
+#ifdef CONFIG_USB_SERIAL_CONSOLE
+ | INITDEV_CONSOLE_MASK
+#endif
+#if defined(CONFIG_USB_STORAGE) || defined(CONFIG_BLK_DEV_UB)
+ | INITDEV_BLOCK_MASK
+#endif
+ | INITDEV_NETDEV_MASK;
+
struct usb_hub {
struct device *intfdev; /* the "interface" device */
struct usb_device *hdev;
@@ -73,6 +87,7 @@ struct usb_hub {
unsigned limited_power:1;
unsigned quiescing:1;
unsigned disconnected:1;
+ unsigned probing:1;
unsigned has_indicators:1;
u8 indicator[USB_MAXCHILDREN];
@@ -1079,6 +1094,9 @@ static int hub_configure(struct usb_hub *hub,
if (hub->has_indicators && blinkenlights)
hub->indicator [0] = INDICATOR_CYCLE;
+ hub->probing = 1;
+ initdev_found(usb_initdev_mask);
+
hub_activate(hub, HUB_INIT);
return 0;
@@ -1124,6 +1142,9 @@ static void hub_disconnect(struct usb_interface *intf)
usb_buffer_free(hub->hdev, sizeof(*hub->buffer), hub->buffer,
hub->buffer_dma);
+ if (hub->probing)
+ initdev_probe_done(usb_initdev_mask);
+
kref_put(&hub->kref, hub_release);
}
@@ -3135,6 +3156,11 @@ static void hub_events(void)
portstatus, portchange);
} /* end for i */
+ if (hub->probing) {
+ hub->probing = 0;
+ initdev_probe_done(usb_initdev_mask);
+ }
+
/* deal with hub status changes */
if (test_and_clear_bit(0, hub->event_bits) == 0)
; /* do nothing */
^ permalink raw reply related
* [PATCH 1/7 v6.1] initdev:kernel:initdev synchronization framework
From: David VomLehn @ 2009-08-04 22:15 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, linux-usb, greg, linux-scsi, netdev, arjan
This patch adds the initdev infrastructure used by the rest of the patches. See
Documentation/driver-model/initdev.txt for details on these functions.
Signed-off-by: David VomLehn <dvomlehn@cisco.com>
---
Documentation/driver-model/initdev.txt | 91 +++++++++++++++++
drivers/base/Makefile | 3 +-
drivers/base/base.h | 1 +
drivers/base/initdev.c | 170 ++++++++++++++++++++++++++++++++
include/linux/device.h | 51 ++++++++++
5 files changed, 315 insertions(+), 1 deletions(-)
diff --git a/Documentation/driver-model/initdev.txt b/Documentation/driver-model/initdev.txt
new file mode 100644
index 0000000..0bb4bc0
--- /dev/null
+++ b/Documentation/driver-model/initdev.txt
@@ -0,0 +1,91 @@
+Init Device Discovery Synchronization
+=====================================
+Init devices are those devices that must be used or configured before
+starting up the /bin/init process. They may be explicitly specified as
+kernel command line parameters, such as console=ttyUSB0,115200, or
+implicitly specified, such as ip=dhcp.
+
+Earlier versions of the Linux kernel used a single-threaded approach to
+boot initialization. This took a number of seconds, which meant that
+devices were generally set up before being used or configured. Modern
+kernels use a multithreaded approach, which requires synchronization between
+code that probes and initializes init devices, and code that uses and
+configures them. Support of fine-grained boot concurrency requires
+distinguishing between types of init devices, so that devices can be used as
+soon as they are initialized.
+
+There are several types of init devices:
+- consoles
+- network devices
+- block devices
+
+There is a distinction between the hardware type and the init device type.
+From the hardware view, most any serial device can be used as a console,
+but console support is generally configured separately. For example, USB
+serial devices should be considered console init devices only if the
+kernel is configured to support this usage. This is done by enabling the
+CONFIG_USB_SERIAL_CONSOLE option. If this option is disabled, the USB bus
+driver should not report that it has found any console devices.
+
+The sequence for buses with asynchronously-discoverable init devices is:
+1. As each possible init devices is discovered, call initdev_found.
+2. As initialization is complete for each device, call
+ initdev_probe_done.
+
+Per-Device Functions
+--------------------
+Functions used to indicate the status of asynchronous device discovery on
+a device-by-device basis are:
+
+initdev_found(int initdev_mask)
+ This function must be called each time a possible init device device
+ is found. It is passed a bit mask created by ORing any of the
+ following flags that apply to the device found:
+ INITDEV_CONSOLE_MASK
+ INITDEV_NETDEV_MASK
+ INITDEV_BLOCK_MASK
+ There is no need to call this function for a given device if it is
+ known that it cannot be used as a init device. If it is not
+ possible to determine whether a device is usable as a init device,
+ or the specific type of a init device, the argument INITDEV_ANY_MASK
+ should be passed. This should be used only when necessary, as it
+ reduces the level of boot-time concurrency.
+
+initdev_probe_done(int initdev_mask)
+ This function indicates that initialization is complete for a device
+ which may be one of the init device types indicated by initdev_mask.
+ Note that calling this function does not imply that device
+ initialization has been successful; if initdev_found is called for a
+ device, initdev_probe_done must be called even if an error occurred.
+
+Some rules about correct usage:
+o Each call to initdev_found *must* be matched by a call to
+ initdev_probe_done.
+o The value of initdev_mask passed to initdev_found and
+ initdev_probe_done for a given device must be identical.
+
+Subsystem Functions
+-------------------
+Boot devices are registered with the appropriate subsystem as they are found
+Each subsystem determines when the init devices is manages are ready for use.
+
+initdev_wait(enum initdev_type type, bool (*done)(void))
+ Wait until one of two conditions is met:
+ o All possible init devices of the given type have been probed
+ o The "done" function returns true
+
+ The type is one of:
+ INITDEV_CONSOLE_TYPE
+ INITDEV_NETDEV_TYPE
+ INITDEV_BLOCK_TYPE
+ The "done" function is subsystem-dependent and returns true if all
+ init devices required for that subsystem to continue booting have
+ been registered. Registration is indicated through use of the
+ initdev_registered function. If done always returns false,
+ initdev_wait will not return until all possible init devices of the
+ given type have been probed.
+
+initdev_registered(enum initdev_type type)
+ Called by each software subsystem that handles init devices of a given
+ type. For example, register_console would call this function with
+ a type of INITDEV_CONSOLE_TYPE.
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index b5b8ba5..a288a46 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -3,7 +3,8 @@
obj-y := core.o sys.o bus.o dd.o \
driver.o class.o platform.o \
cpu.o firmware.o init.o map.o devres.o \
- attribute_container.o transport_class.o
+ attribute_container.o transport_class.o \
+ initdev.o
obj-y += power/
obj-$(CONFIG_HAS_DMA) += dma-mapping.o
obj-$(CONFIG_ISA) += isa.o
diff --git a/drivers/base/base.h b/drivers/base/base.h
index b528145..90dede0 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -90,6 +90,7 @@ struct device_private {
container_of(obj, struct device_private, knode_bus)
/* initialisation functions */
+extern int initdevs_init(void);
extern int devices_init(void);
extern int buses_init(void);
extern int classes_init(void);
diff --git a/drivers/base/initdev.c b/drivers/base/initdev.c
new file mode 100644
index 0000000..ae08adc
--- /dev/null
+++ b/drivers/base/initdev.c
@@ -0,0 +1,170 @@
+/*
+ * initdev.c
+ *
+ * Primitives to synchronize boot device discovery and initialization with
+ * their boot-time use.
+ *
+ * Copyright (C) 2009 Scientific-Atlanta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author: David VomLehn
+ */
+
+#include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/device.h>
+#include <linux/sched.h>
+#include <linux/async.h>
+
+/*
+ * Information about how many boot devices have been found, but for which
+ * probing activity is not yet complete, by type, along with wait queues on
+ * which a wake up will be done as the probing completes.
+ */
+static struct {
+ atomic_t pending;
+ wait_queue_head_t wq;
+} initdev_info[INITDEV_TYPE_NUM] = {
+ [INITDEV_CONSOLE_TYPE] = {
+ ATOMIC_INIT(0),
+ __WAIT_QUEUE_HEAD_INITIALIZER(initdev_info
+ [INITDEV_CONSOLE_TYPE].wq)
+ },
+ [INITDEV_NETDEV_TYPE] = {
+ ATOMIC_INIT(0),
+ __WAIT_QUEUE_HEAD_INITIALIZER(initdev_info
+ [INITDEV_NETDEV_TYPE].wq)
+ },
+ [INITDEV_BLOCK_TYPE] = {
+ ATOMIC_INIT(0),
+ __WAIT_QUEUE_HEAD_INITIALIZER(initdev_info
+ [INITDEV_BLOCK_TYPE].wq)
+ },
+};
+
+/*
+ * Adds a console bit to the mask of boot devices if network consoles are used
+ * @mask: Starting mask
+ *
+ * Returns mask with the %INITDEV_CONSOLE_TYPE bit set if network consoles are
+ * configured into the system, since, from the boot device standpoint,
+ * a network device might be used as a console.
+ */
+#ifdef CONFIG_NETCONSOLE
+static int initdev_add_netconsole(int initdev_mask)
+{
+ return (initdev_mask & INITDEV_NETDEV_MASK) ?
+ (initdev_mask | INITDEV_CONSOLE_MASK) : initdev_mask;
+}
+#else
+static int initdev_add_netconsole(int initdev_mask)
+{
+ return initdev_mask;
+}
+#endif
+
+/**
+ * initdev_found - called when a new device is discovered on a bus.
+ * @initdev_mask: Mask for possible devices
+ *
+ * The initdev_mask allows a caller to specify a restricted set of boot
+ * devices that might be probed. For example, if the bus is USB, it may be
+ * the case that %CONFIG_USB_SERIAL_CONSOLE is not defined. The call to this
+ * function might then omit %INITDEV_CONSOLE_MASK from the mask. When we go to
+ * wait for console devices, we won't wait for USB probing to complete. If
+ * a given bus type has no way to determine the type of device being probed,
+ * it can simply pass %INITDEV_ALL_MASK, but finer granularity will generally
+ * result in faster boot times.
+ *
+ * Note that each call to initdev_found must be paired with a call to
+ * initdev_probe_done().
+ */
+void initdev_found(int initdev_mask)
+{
+ int i;
+
+ initdev_mask = initdev_add_netconsole(initdev_mask);
+
+ for (i = 0; i < ARRAY_SIZE(initdev_info); i++) {
+ if (initdev_mask & (1 << i))
+ atomic_inc(&initdev_info[i].pending);
+ }
+}
+
+/**
+ * initdev_probe_done - indicate probing is complete for a device on a bus
+ * @initdev_mask: Mask for possible devices
+ *
+ * The definition of probing complete for a given device is that the driver
+ * for that device must have been able to register its presence with its
+ * associated subsystem. So, devices supporting consoles must have called
+ * register_console(), networking device must have called register_netdevice(),
+ * etc.
+ *
+ * Note that each call to initdev_probe_done() must be paired with a call to
+ * initdev_found().
+ */
+void initdev_probe_done(int initdev_mask)
+{
+ int i;
+
+ initdev_mask = initdev_add_netconsole(initdev_mask);
+
+ for (i = 0; i < ARRAY_SIZE(initdev_info); i++) {
+ /* Decrement the count of pending probes and, if we reach
+ * zero, wake up all waiters. */
+ if (initdev_mask & (1 << i)) {
+ if (atomic_dec_and_test(&initdev_info[i].pending))
+ wake_up_all(&initdev_info[i].wq);
+ }
+ }
+}
+
+/**
+ * initdev_wait - wait until desired boot devices are registered or probing done
+ * @type: Type of boot device to wait for
+ * @done: Pointer to function that determines whether all boot devices
+ * have been acquired.
+ *
+ * This function exits if all devices of the given @type have been probed or
+ * the passed function indicates that all the expected boot devices have been
+ * acquired. Say, for example the kernel command line specifies the name of
+ * a boot device to use. The @done function can check to see whether that
+ * device has been registered and, if so, return true. This function will
+ * return even though probing has not completed on some devices, which allows
+ * faster boot times.
+ */
+void initdev_wait(enum initdev_type type, bool (*done)(void))
+{
+ /* Wait until initdev_probe_done has been called for all of the devices
+ * of the type for which we are waiting, or for some minimal set of
+ * those devices to be ready. This last condition is defined by the
+ * caller through the implementation of the callback function. */
+ wait_event(initdev_info[type].wq,
+ done() || atomic_read(&initdev_info[type].pending) == 0);
+}
+
+/**
+ * initdev_registered - indicate boot device registration by its subsystem
+ * @type: Type of boot device
+ *
+ * This will wake up all threads waiting on a given boot device @type so that
+ * they can see if they are ready to continue.
+ */
+void initdev_registered(enum initdev_type type)
+{
+ wake_up_all(&initdev_info[type].wq);
+}
diff --git a/include/linux/device.h b/include/linux/device.h
index aebb810..cd3f394 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -90,6 +90,57 @@ int __must_check bus_for_each_drv(struct bus_type *bus,
void bus_sort_breadthfirst(struct bus_type *bus,
int (*compare)(const struct device *a,
const struct device *b));
+
+/*
+ * Definitions for synchronizing discovery of asynchronously-discoverable
+ * devices with their use as boot devices.
+ */
+/*
+ * Define boot device types. These are not the same as the device classes
+ * supported by various buses, but are tied to support of specific Linux kernel
+ * devices. For example, USB knows about serial devices, but a serial device
+ * is only a %INITDEV_CONSOLE_TYPE if %CONFIG_USB_SERIAL_CONSOLE is defined.
+ */
+#define INITDEV_CONSOLE_MASK (1 << INITDEV_CONSOLE_TYPE)
+#define INITDEV_NETDEV_MASK (1 << INITDEV_NETDEV_TYPE)
+#define INITDEV_BLOCK_MASK (1 << INITDEV_BLOCK_TYPE)
+#define INITDEV_ANY_MASK ((1 << INITDEV_TYPE_NUM) - 1)
+
+enum initdev_type {
+ INITDEV_CONSOLE_TYPE, /* Device usable as a console */
+ INITDEV_NETDEV_TYPE, /* Autoconfigurable network device */
+ INITDEV_BLOCK_TYPE, /* Block device for boot filesystem */
+ INITDEV_TYPE_NUM /* Number of boot devices */
+};
+
+#ifndef MODULE
+extern void initdev_found(int initdev_mask);
+extern void initdev_type_found(int initdev_mask, enum initdev_type type);
+extern void initdev_probe_done(int initdev_mask);
+extern void initdev_registered(enum initdev_type type);
+extern void initdev_wait(enum initdev_type type, bool (*done)(void));
+#else
+static inline void initdev_found(int initdev_mask)
+{
+}
+
+static inline void initdev_type_found(int initdev_mask, enum initdev_type type)
+{
+}
+
+static inline void initdev_probe_done(int initdev_mask)
+{
+}
+
+static inline void initdev_registered(enum initdev_type type)
+{
+}
+
+static inline void initdev_wait(enum initdev_type type, bool (*done)(void))
+{
+}
+#endif
+
/*
* Bus notifiers: Get notified of addition/removal of devices
* and binding/unbinding of drivers to devices.
^ permalink raw reply related
* [PATCH 0/7] initdev:kernel:Introduction to initdev synchronization patchset
From: David VomLehn @ 2009-08-04 22:14 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, linux-usb, greg, linux-scsi, netdev, arjan
The kernel command line parameters "ip", "root", and "console" take devices
as arguments. These are termed "init devices" since devices specified by
these parameters are used during kernel initialization. Some init devices
take a long time to be discovered and made ready for use, USB devices being
a prime example. This patch provides two, related, functionalities:
o Wait for device setup. Provides synchronization between use of
init devices and their setup so that attempts to use them can be
delayed until the devices are ready.
o Prompt device wait termination. Terminates waits for device
discovery as soon as it is know that no more devices remain to be
discovered. For example, consider an embedded device that may or
may not have a USB console. As soon as all USB devices have been
discovered, there is no more need to wait for a console that isn't
attached, and a headless system boot can continue.
This patch supports device discovery on USB and SCSI buses but provides a
framework for other bus types. Where possible, specific device types can
be specified so that, for example, waiting on a console does not prevent
mounting a root filesystem.
A secondary consequence of this patch is that the only remaining use of the
rootwait kernel parameter is to wait for a root device that is not plugged
in at boot.
This introduction is followed by 7 small-ish patches. It would be possible
to combine these but this patch touches the console, networking, and block
device areas and it is hoped that splitting the changes into smaller,
targeted chunks will make it easier for people in those areas to review it.
1 Basic initdev infrastructure
2 USB device discovery notification
3 Wait for console
4 Wait for network devices
5 USB and SCSI block device notification
6 Additional SCSI block device notification for asynchronous function
7 Wait for block device used for root
(Many thanks to Alan Stern, who said we could solve this without offensive
timeouts and then set about doing the integration into core USB and SCSI
code)
Signed-off-by: David VomLehn <dvomlehn@cisco.com>
---
^ permalink raw reply
* Re: Kernel oops on setting sky2 interfaces down
From: Rene Mayrhofer @ 2009-08-04 21:31 UTC (permalink / raw)
To: Mike McCormack; +Cc: Stephen Hemminger, netdev, Richard Leitner
In-Reply-To: <4A78190C.1080909@ring3k.org>
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Mike McCormack wrote:
> 2009/8/4 Rene Mayrhofer <rene.mayrhofer@gibraltar.at>:
>
>> Does anybody have an idea on what might be wrong in sky2_down?
>
> I had a look into this, and noticed that we don't hold phy_lock when calling
> sky2_phy_power_down() in sky2_down(). sky2_phy_power_down() does some PCI
> manipulation, so it's possible this could cause bad things to happen...
>
> Does the following patch help?
It does certainly change things:
[~]# [ 394.651649] ------------[ cut here ]------------
[ 394.655499] kernel BUG at net/core/skbuff.c:1086!
[ 394.655499] invalid opcode: 0000 [#1] PREEMPT SMP
[ 394.655499] last sysfs file:
/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
[ 394.655499] Modules linked in: xt_multiport cpufreq_userspace xt_DSCP
xt_length xt_mark xt_dscp xt_MARK xt_CONNMARK xt_comment xt_policy
ipt_REDIRECT ip6t_LOG xt_tcpudp ip6table_mangle iptable_mangle
ip6table_filter ip6_tables sit tunnel4 8021q garp stp llc ipt_LOG
xt_limit xt_state iptable_nat iptable_filter ip_tables x_tables dm_mod
p4_clockmod speedstep_lib freq_table tun imq nf_nat_ftp nf_nat
nf_conntrack_ftp nf_conntrack_ipv6 nf_conntrack_ipv4 nf_conntrack
nf_defrag_ipv4 ipv6 evdev parport_pc parport i2c_i801 iTCO_wdt serio_raw
i2c_core rng_core pcspkr intel_agp loop aufs exportfs nls_utf8 nls_cp437
ide_generic sd_mod ide_gd_mod ata_generic pata_acpi skge ata_piix piix
ide_pci_generic ide_core sky2 thermal_sys
[ 394.655499]
[ 394.655499] Pid: 0, comm: swapper Not tainted (2.6.30.4 #2)
[ 394.655499] EIP: 0060:[<c045e0cd>] EFLAGS: 00010206 CPU: 0
[ 394.655499] EIP is at skb_put+0x23/0x8c
[ 394.655499] EAX: e1ebb022 EBX: e1eb4880 ECX: e1eb4880 EDX: 000000cc
[ 394.655499] ESI: 000000cc EDI: f71f145c EBP: c065be64 ESP: c065be58
[ 394.655499] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 394.655499] Process swapper (pid: 0, ti=c065a000 task=c061d300
task.ti=c065a000)
[ 394.655499] Stack:
[ 394.655499] 9d5834df e1eb4880 00000600 c065beb0 f80ea72f 000202d2
00000040 f71e9388
[ 394.655499] 97a234df f71e9380 f71e9000 f690cb80 e1ff8030 00000002
9d5834df c065bec8
[ 394.655499] f71e9380 000000cc 9d5834df f71e9388 00000040 00000000
c065bedc c0463ce6
[ 394.655499] Call Trace:
[ 394.655499] [<f80ea72f>] ? skge_poll+0x41f/0x5b6 [skge]
[ 394.655499] [<c0463ce6>] ? net_rx_action+0x9e/0x1a2
[ 394.655499] [<c0237b6e>] ? __do_softirq+0xb2/0x188
[ 394.655499] [<c0237c83>] ? do_softirq+0x3f/0x5c
[ 394.655499] [<c0237e0d>] ? irq_exit+0x37/0x80
[ 394.655499] [<c0204cd2>] ? do_IRQ+0x79/0xa0
[ 394.655499] [<c02034d0>] ? common_interrupt+0x30/0x38
[ 394.655499] [<c0209ade>] ? mwait_idle+0xad/0x116
[ 394.655499] [<c0201eb4>] ? cpu_idle+0x96/0xc6
[ 394.655499] [<c04dbb19>] ? rest_init+0x75/0x88
[ 394.655499] [<c0660a16>] ? start_kernel+0x32d/0x343
[ 394.655499] [<c0660078>] ? __init_begin+0x78/0x8e
[ 394.655499] Code: ff 8d 65 f8 5b 5e 5d c3 55 89 c1 89 e5 56 89 d6 53
83 ec 04 65 a1 14 00 00 00 89 45 f4 31 c0 83 79 58 00 8b 81 a8 00 00 00
74 04 <0f> 0b eb fe 8d 1c 10 01 51 54 3b 99 ac 00 00 00 89 99 a8 00 00
[ 394.655499] EIP: [<c045e0cd>] skb_put+0x23/0x8c SS:ESP 0068:c065be58
[ 394.913195] ---[ end trace d93328fae040abf9 ]---
[ 394.918175] Kernel panic - not syncing: Fatal exception in interrupt
[ 394.924926] Pid: 0, comm: swapper Tainted: G D 2.6.30.4 #2
[ 394.931491] Call Trace:
[ 394.934153] [<c04eb041>] ? printk+0x1d/0x30
[ 394.938722] [<c04eaf7f>] panic+0x53/0xf8
[ 394.943025] [<c0206368>] oops_end+0x9f/0xbf
[ 394.947565] [<c020656f>] die+0x5f/0x77
[ 394.951672] [<c0203ae1>] do_trap+0x9f/0xca
[ 394.956129] [<c0203ea8>] ? do_invalid_op+0x0/0xa2
[ 394.961254] [<c0203f2f>] do_invalid_op+0x87/0xa2
[ 394.966274] [<c045e0cd>] ? skb_put+0x23/0x8c
[ 394.970951] [<c04a7672>] ? udp_rcv+0x21/0x34
[ 394.975611] [<c0487922>] ? ip_local_deliver_finish+0x197/0x1ef
[ 394.981912] [<c04879e9>] ? ip_local_deliver+0x6f/0x89
[ 394.987390] [<c0487527>] ? ip_rcv_finish+0x28b/0x2b2
[ 394.992768] [<c04ee71a>] error_code+0x7a/0x80
[ 394.997517] [<c045e0cd>] ? skb_put+0x23/0x8c
[ 395.002192] [<f80ea72f>] skge_poll+0x41f/0x5b6 [skge]
[ 395.007671] [<c0463ce6>] net_rx_action+0x9e/0x1a2
[ 395.012798] [<c0237b6e>] __do_softirq+0xb2/0x188
[ 395.017818] [<c0237c83>] do_softirq+0x3f/0x5c
[ 395.022561] [<c0237e0d>] irq_exit+0x37/0x80
[ 395.027122] [<c0204cd2>] do_IRQ+0x79/0xa0
[ 395.031502] [<c02034d0>] common_interrupt+0x30/0x38
[ 395.036815] [<c0209ade>] ? mwait_idle+0xad/0x116
[ 395.041844] [<c0201eb4>] cpu_idle+0x96/0xc6
[ 395.046397] [<c04dbb19>] rest_init+0x75/0x88
[ 395.051049] [<c0660a16>] start_kernel+0x32d/0x343
[ 395.056178] [<c0660078>] __init_begin+0x78/0x8e
[ 395.061107] Rebooting in 30 seconds..
Interesting that there are no sky2 errors anymore but that skge
oopses... After a reboot and rmmod skge before networking restart, it
suddenly starts to work! I only get these errors during ifdown/ifup:
[ 534.141904] sky2 wan: disabling interface
[ 534.342464] sky2 gibsrv: disabling interface
[ 534.679531] sky2 dmz: disabling interface
[ 535.000035] sky2 0000:01:00.0: device status error
[ 535.000043] sky2 0000:03:00.0: device status error
[ 535.017519] sky2 lan: disabling interface
[ 536.000030] sky2 0000:01:00.0: device status error
[ 536.000038] sky2 0000:03:00.0: device status error
[ 536.000042] sky2 0000:04:00.0: device status error
[ 537.000028] sky2 0000:01:00.0: device status error
[ 537.000035] sky2 0000:03:00.0: device status error
[ 537.000040] sky2 0000:04:00.0: device status error
[ 537.009455] sky2 0000:01:00.0: wan: phy I/O error
[ 537.014229] sky2 0000:01:00.0: wan: phy I/O error
[ 537.018975] sky2 0000:01:00.0: wan: phy I/O error
[ 537.023716] sky2 0000:01:00.0: wan: phy I/O error
[ 537.028463] sky2 0000:01:00.0: wan: phy I/O error
[ 537.033210] sky2 0000:01:00.0: wan: phy I/O error
[ 537.037950] sky2 0000:01:00.0: wan: phy I/O error
[ 537.042694] sky2 0000:01:00.0: wan: phy I/O error
[ 537.047435] sky2 0000:01:00.0: wan: phy I/O error
[ 537.052177] sky2 0000:01:00.0: wan: phy I/O error
[ 537.057639] sky2 wan: enabling interface
[ 537.057852] ADDRCONF(NETDEV_UP): wan: link is not ready
[ 537.288286] sky2 gibsrv: enabling interface
[ 537.288459] ADDRCONF(NETDEV_UP): gibsrv: link is not ready
[ 537.627866] sky2 0000:03:00.0: dmz: phy I/O error
[ 537.632634] sky2 0000:03:00.0: dmz: phy I/O error
[ 537.637377] sky2 0000:03:00.0: dmz: phy I/O error
[ 537.642118] sky2 0000:03:00.0: dmz: phy I/O error
[ 537.646862] sky2 0000:03:00.0: dmz: phy I/O error
[ 537.651610] sky2 0000:03:00.0: dmz: phy I/O error
[ 537.656353] sky2 0000:03:00.0: dmz: phy I/O error
[ 537.661097] sky2 0000:03:00.0: dmz: phy I/O error
[ 537.665846] sky2 0000:03:00.0: dmz: phy I/O error
[ 537.670589] sky2 0000:03:00.0: dmz: phy I/O error
[ 537.676143] sky2 dmz: enabling interface
[ 537.676317] ADDRCONF(NETDEV_UP): dmz: link is not ready
[ 538.000031] sky2 0000:01:00.0: device status error
[ 538.000039] sky2 0000:03:00.0: device status error
[ 538.000044] sky2 0000:04:00.0: device status error
[ 538.024201] sky2 0000:04:00.0: lan: phy I/O error
[ 538.028971] sky2 0000:04:00.0: lan: phy I/O error
[ 538.033712] sky2 0000:04:00.0: lan: phy I/O error
[ 538.038455] sky2 0000:04:00.0: lan: phy I/O error
[ 538.043199] sky2 0000:04:00.0: lan: phy I/O error
[ 538.047939] sky2 0000:04:00.0: lan: phy I/O error
[ 538.052681] sky2 0000:04:00.0: lan: phy I/O error
[ 538.057424] sky2 0000:04:00.0: lan: phy I/O error
[ 538.062167] sky2 0000:04:00.0: lan: phy I/O error
[ 538.066908] sky2 0000:04:00.0: lan: phy I/O error
[ 538.072982] sky2 lan: enabling interface
[ 538.073196] ADDRCONF(NETDEV_UP): lan: link is not ready
[ 539.000021] sky2 0000:01:00.0: device status error
[ 539.000029] sky2 0000:03:00.0: device status error
[ 539.000034] sky2 0000:04:00.0: device status error
[ 539.447535] tun6to4: Disabled Privacy Extensions
[ 540.000022] sky2 0000:01:00.0: device status error
[ 540.000033] sky2 0000:03:00.0: device status error
[ 540.000039] sky2 0000:04:00.0: device status error
[ 541.000020] sky2 0000:01:00.0: device status error
[ 541.000032] sky2 0000:03:00.0: device status error
[ 541.000038] sky2 0000:04:00.0: device status error
[ 542.000025] sky2 0000:01:00.0: device status error
[ 542.000035] sky2 0000:03:00.0: device status error
[ 542.000046] sky2 0000:04:00.0: device status error
[ 543.000030] sky2 0000:01:00.0: device status error
[ 543.000044] sky2 0000:03:00.0: device status error
[ 543.000054] sky2 0000:04:00.0: device status error
Unfortunately, these errors continue and the device refuses to send or
receive any packets afterwards.
I will next try to use sky2.c from netdev git, as suggested.
best regards,
Rene
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iEYEARECAAYFAkp4qMUACgkQq7SPDcPCS94EPQCgx6nYmqUaZQbnXqNUTYPOulfA
bGMAn2oSt+KedkNOBGpF1y55JIjCdstl
=fH02
-----END PGP SIGNATURE-----
^ permalink raw reply
* [RFC PATCH v1 1/2] lsm: Add hooks to the TUN driver
From: Paul Moore @ 2009-08-04 21:21 UTC (permalink / raw)
To: netdev, linux-security-module, selinux
In-Reply-To: <20090804211304.10798.65601.stgit@flek.lan>
The TUN driver lacks any LSM hooks which makes it difficult for LSM modules,
such as SELinux, to enforce access controls on network traffic generated by
TUN users; this is particularly problematic for virtualization apps such as
QEMU and KVM. This patch adds three new LSM hooks designed to control the
creation and attachment of TUN devices, the hooks are:
* security_tun_dev_create()
Provides access control for the creation of new TUN devices
* security_tun_dev_post_create()
Provides the ability to create the necessary socket LSM state for newly
created TUN devices
* security_tun_dev_attach()
Provides access control for attaching to existing, persistent TUN devices
and the ability to update the TUN device's socket LSM state as necessary
---
drivers/net/tun.c | 41 +++++++++++++++++++++++------------------
include/linux/security.h | 34 ++++++++++++++++++++++++++++++++++
security/commoncap.c | 26 ++++++++++++++++++++++++++
security/security.c | 18 ++++++++++++++++++
4 files changed, 101 insertions(+), 18 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 027f7ab..f26c1fe 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -130,28 +130,22 @@ static inline struct tun_sock *tun_sk(struct sock *sk)
static int tun_attach(struct tun_struct *tun, struct file *file)
{
struct tun_file *tfile = file->private_data;
- const struct cred *cred = current_cred();
- int err;
+ int err = 0;
ASSERT_RTNL();
- /* Check permissions */
- if (((tun->owner != -1 && cred->euid != tun->owner) ||
- (tun->group != -1 && !in_egroup_p(tun->group))) &&
- !capable(CAP_NET_ADMIN))
- return -EPERM;
-
netif_tx_lock_bh(tun->dev);
- err = -EINVAL;
- if (tfile->tun)
+ if (tfile->tun) {
+ err = -EINVAL;
goto out;
+ }
- err = -EBUSY;
- if (tun->tfile)
+ if (tun->tfile) {
+ err = -EBUSY;
goto out;
+ }
- err = 0;
tfile->tun = tun;
tun->tfile = tfile;
dev_hold(tun->dev);
@@ -922,6 +916,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
struct sock *sk;
struct tun_struct *tun;
struct net_device *dev;
+ const struct cred *cred = current_cred();
int err;
dev = __dev_get_by_name(net, ifr->ifr_name);
@@ -935,6 +930,13 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
else
return -EINVAL;
+ if ((tun->owner != -1 && cred->euid != tun->owner) ||
+ (tun->group != -1 && !in_egroup_p(tun->group)))
+ return -EPERM;
+ err = security_tun_dev_attach(tun->sk);
+ if (err < 0)
+ return err;
+
err = tun_attach(tun, file);
if (err < 0)
return err;
@@ -943,10 +945,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
char *name;
unsigned long flags = 0;
- err = -EINVAL;
-
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
+ err = security_tun_dev_create();
+ if (err < 0)
+ return err;
/* Set dev type */
if (ifr->ifr_flags & IFF_TUN) {
@@ -957,8 +958,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
/* TAP device */
flags |= TUN_TAP_DEV;
name = "tap%d";
- } else
+ } else {
+ err = -EINVAL;
goto failed;
+ }
if (*ifr->ifr_name)
name = ifr->ifr_name;
@@ -989,6 +992,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
tun->sk = sk;
container_of(sk, struct tun_sock, sk)->tun = tun;
+ security_tun_dev_post_create(sk);
+
tun_net_init(dev);
if (strchr(dev->name, '%')) {
diff --git a/include/linux/security.h b/include/linux/security.h
index 5eff459..67f5d91 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -91,6 +91,9 @@ struct seq_file;
extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
extern int cap_netlink_recv(struct sk_buff *skb, int cap);
+extern int cap_tun_dev_create(void);
+extern int cap_tun_dev_attach(void);
+
extern unsigned long mmap_min_addr;
/*
* Values used in the task_security_ops calls
@@ -974,6 +977,17 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* Sets the connection's peersid to the secmark on skb.
* @req_classify_flow:
* Sets the flow's sid to the openreq sid.
+ * @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.
+ * @tun_sk contains the newly created sock 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
+ * associated with the TUN device's sock structure.
+ * @tun_sk contains the existing sock structure.
*
* Security hooks for XFRM operations.
*
@@ -1572,6 +1586,9 @@ struct security_operations {
void (*inet_csk_clone) (struct sock *newsk, const struct request_sock *req);
void (*inet_conn_established) (struct sock *sk, struct sk_buff *skb);
void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);
+ int (*tun_dev_create)(void);
+ void (*tun_dev_post_create)(struct sock *tun_sk);
+ int (*tun_dev_attach)(struct sock *tun_sk);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -2557,6 +2574,9 @@ void security_inet_csk_clone(struct sock *newsk,
const struct request_sock *req);
void security_inet_conn_established(struct sock *sk,
struct sk_buff *skb);
+int security_tun_dev_create(void);
+void security_tun_dev_post_create(struct sock *tun_sk);
+int security_tun_dev_attach(struct sock *tun_sk);
#else /* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct socket *sock,
@@ -2707,6 +2727,20 @@ static inline void security_inet_conn_established(struct sock *sk,
struct sk_buff *skb)
{
}
+
+static inline int security_tun_dev_create(void)
+{
+ return cap_tun_dev_create();
+}
+
+static inline void security_tun_dev_post_create(struct sock *tun_sk)
+{
+}
+
+static inline int security_tun_dev_attach(struct sock *tun_sk)
+{
+ return cap_tun_dev_attach();
+}
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --git a/security/commoncap.c b/security/commoncap.c
index 48b7e02..07125a6 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -984,3 +984,29 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
cap_sys_admin = 1;
return __vm_enough_memory(mm, pages, cap_sys_admin);
}
+
+/**
+ * cap_tun_dev_create - Determine if creation of a new TUN device is allowed
+ *
+ * Determine if the user is allowed to create a new TUN device, historically
+ * this has always required the CAP_NET_ADMIN permission.
+ */
+int cap_tun_dev_create(void)
+{
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ return 0;
+}
+
+/**
+ * cap_tun_dev_attach - Determine if attaching to an TUN device is allowed
+ *
+ * Determine if the user is allowed to attach to an existing persistent TUN
+ * device, historically this has always required the CAP_NET_ADMIN permission.
+ */
+int cap_tun_dev_attach(void)
+{
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ return 0;
+}
diff --git a/security/security.c b/security/security.c
index dc7674f..14ebf82 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1112,6 +1112,24 @@ void security_inet_conn_established(struct sock *sk,
security_ops->inet_conn_established(sk, skb);
}
+int security_tun_dev_create(void)
+{
+ return security_ops->tun_dev_create();
+}
+EXPORT_SYMBOL(security_tun_dev_create);
+
+void security_tun_dev_post_create(struct sock *tun_sk)
+{
+ return security_ops->tun_dev_post_create(tun_sk);
+}
+EXPORT_SYMBOL(security_tun_dev_post_create);
+
+int security_tun_dev_attach(struct sock *tun_sk)
+{
+ return security_ops->tun_dev_attach(tun_sk);
+}
+EXPORT_SYMBOL(security_tun_dev_attach);
+
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
^ permalink raw reply related
* [RFC PATCH v1 0/2] The Long Lost TUN LSM Hooks
From: Paul Moore @ 2009-08-04 21:21 UTC (permalink / raw)
To: netdev, linux-security-module, selinux
While drivers in general aren't good places for LSM hooks the TUN driver is
a bit different because of how it handles sockets and network traffic. The
problem lies in the fact that the TUN driver creates a sock structure to use
when sending network traffic but the sock is never put through the same LSM
setup/control as other sock structures on the system which makes enforcing
security on TUN generated traffic difficult for some LSMs. This patch set
adds three new LSM hooks, all specific to the TUN driver (none of the existing
hooks made sense, trust me we tried), to control and monitor the creating and
attachment of TUN devices.
The necessary support for SELinux is also included in this patch with support
for Smack and TOMOYO absent; although I suspect there will be no changes needed
for either of those LSMs.
--
NOTE: These patches are truly RFC, please let me know how you feel about these
new hooks. I've booted a kernel with these changes but I'm having some
problems today with my Rawhide/KVM test machine so I'm having mixed luck
testing this - no regressions, but no real TUN testing either.
---
Paul Moore (2):
selinux: Support for the new TUN LSM hooks
lsm: Add hooks to the TUN driver
drivers/net/tun.c | 41 ++++++++-------
include/linux/security.h | 34 +++++++++++++
security/commoncap.c | 26 ++++++++++
security/security.c | 18 +++++++
security/selinux/hooks.c | 76 +++++++++++++++++++++++++++-
security/selinux/include/av_inherit.h | 1
security/selinux/include/av_permissions.h | 22 ++++++++
security/selinux/include/class_to_string.h | 1
security/selinux/include/flask.h | 1
security/selinux/include/security.h | 2 +
security/selinux/selinuxfs.c | 3 +
security/selinux/ss/services.c | 3 +
12 files changed, 207 insertions(+), 21 deletions(-)
^ permalink raw reply
* [RFC PATCH v1 2/2] selinux: Support for the new TUN LSM hooks
From: Paul Moore @ 2009-08-04 21:22 UTC (permalink / raw)
To: netdev, linux-security-module, selinux
In-Reply-To: <20090804211304.10798.65601.stgit@flek.lan>
Add support for the new TUN LSM hooks: security_tun_dev_create(),
security_tun_dev_post_create() and security_tun_dev_attach(). This includes
the addition of a new object class, tun_socket, which represents the socks
associated with TUN devices. The _tun_dev_create() and _tun_dev_post_create()
hooks are fairly similar to the standard socket functions but _tun_dev_attach()
is a bit special. The _tun_dev_attach() is unique because it involves a
domain attaching to an existing TUN device and its associated tun_socket
object, an operation which does not exist with standard sockets and most
closely resembles a relabel operation.
This patch also includes a new policy capability, tun_perms, to ensure that
the new access controls do not affect older SELinux policies.
--
NOTE: This relies on some changes to the policy to add the new object class
and its associated permissions, I will ensure that the policy is sorted
and merged before pushing this patch upstream. Also, you will notice
that the new tun_socket object class simply inherits the base socket
object class, thoughts?
---
security/selinux/hooks.c | 76 +++++++++++++++++++++++++++-
security/selinux/include/av_inherit.h | 1
security/selinux/include/av_permissions.h | 22 ++++++++
security/selinux/include/class_to_string.h | 1
security/selinux/include/flask.h | 1
security/selinux/include/security.h | 2 +
security/selinux/selinuxfs.c | 3 +
security/selinux/ss/services.c | 3 +
8 files changed, 106 insertions(+), 3 deletions(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 15c2a08..6ba99c2 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -13,8 +13,8 @@
* Eric Paris <eparis@redhat.com>
* Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
* <dgoeddel@trustedcs.com>
- * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
- * Paul Moore <paul.moore@hp.com>
+ * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
+ * Paul Moore <paul.moore@hp.com>
* Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
* Yuichi Nakamura <ynakam@hitachisoft.jp>
*
@@ -4296,6 +4296,75 @@ static void selinux_req_classify_flow(const struct request_sock *req,
fl->secid = req->secid;
}
+static int selinux_tun_dev_create(void)
+{
+ u32 sid;
+ int err;
+
+ err = cap_tun_dev_create();
+ if (err)
+ return err;
+
+ if (!selinux_policycap_tunperm)
+ return 0;
+
+ /* we aren't taking into account the "sockcreate" SID since the socket
+ * that is being created here is not a socket in the traditional sense,
+ * instead it is a private sock, accessible only to the kernel, and
+ * representing a wide range of network traffic spanning multiple
+ * connections unlike traditional sockets - check the TUN driver to
+ * get a better understand of why this socket is special */
+
+ sid = current_sid();
+ return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
+ NULL);
+}
+
+static void selinux_tun_dev_post_create(struct sock *tun_sk)
+{
+ struct sk_security_struct *sksec = tun_sk->sk_security;
+
+ /* see the comments in _tun_dev_create() about why we don't use the
+ * sockcreate SID here */
+
+ /* we don't currently perform any NetLabel based labeling here and it
+ * isn't clear that we would want to do so anyway: while we could apply
+ * labeling without the support of the TUN user the resulting labeled
+ * traffic from the other end of the connection would almost certainly
+ * cause confusion to the TUN user that had no idea network labeling
+ * protocols were being used */
+
+ sksec->sid = current_sid();
+ sksec->sclass = SECCLASS_TUN_SOCKET;
+}
+
+static int selinux_tun_dev_attach(struct sock *tun_sk)
+{
+ struct sk_security_struct *tun_sksec = tun_sk->sk_security;
+ u32 sid;
+ int err;
+
+ err = cap_tun_dev_attach();
+ if (err)
+ return err;
+
+ if (!selinux_policycap_tunperm)
+ return 0;
+
+ sid = current_sid();
+ err = avc_has_perm(sid, tun_sksec->sid, SECCLASS_TUN_SOCKET,
+ TUN_SOCKET__RELABELFROM, NULL);
+ if (err)
+ return err;
+ err = avc_has_perm(sid, sid, SECCLASS_RAWIP_SOCKET,
+ TUN_SOCKET__RELABELTO, NULL);
+ if (err)
+ return err;
+ tun_sksec->sid = sid;
+
+ return 0;
+}
+
static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
{
int err = 0;
@@ -5464,6 +5533,9 @@ static struct security_operations selinux_ops = {
.inet_csk_clone = selinux_inet_csk_clone,
.inet_conn_established = selinux_inet_conn_established,
.req_classify_flow = selinux_req_classify_flow,
+ .tun_dev_create = selinux_tun_dev_create,
+ .tun_dev_post_create = selinux_tun_dev_post_create,
+ .tun_dev_attach = selinux_tun_dev_attach,
#ifdef CONFIG_SECURITY_NETWORK_XFRM
.xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h
index 8377a4b..abedcd7 100644
--- a/security/selinux/include/av_inherit.h
+++ b/security/selinux/include/av_inherit.h
@@ -15,6 +15,7 @@
S_(SECCLASS_KEY_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_UNIX_STREAM_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_UNIX_DGRAM_SOCKET, socket, 0x00400000UL)
+ S_(SECCLASS_TUN_SOCKET, socket, 0x00400000UL)
S_(SECCLASS_IPC, ipc, 0x00000200UL)
S_(SECCLASS_SEM, ipc, 0x00000200UL)
S_(SECCLASS_MSGQ, ipc, 0x00000200UL)
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index d645192..0b41ad5 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -423,6 +423,28 @@
#define UNIX_DGRAM_SOCKET__RECV_MSG 0x00080000UL
#define UNIX_DGRAM_SOCKET__SEND_MSG 0x00100000UL
#define UNIX_DGRAM_SOCKET__NAME_BIND 0x00200000UL
+#define TUN_SOCKET__IOCTL 0x00000001UL
+#define TUN_SOCKET__READ 0x00000002UL
+#define TUN_SOCKET__WRITE 0x00000004UL
+#define TUN_SOCKET__CREATE 0x00000008UL
+#define TUN_SOCKET__GETATTR 0x00000010UL
+#define TUN_SOCKET__SETATTR 0x00000020UL
+#define TUN_SOCKET__LOCK 0x00000040UL
+#define TUN_SOCKET__RELABELFROM 0x00000080UL
+#define TUN_SOCKET__RELABELTO 0x00000100UL
+#define TUN_SOCKET__APPEND 0x00000200UL
+#define TUN_SOCKET__BIND 0x00000400UL
+#define TUN_SOCKET__CONNECT 0x00000800UL
+#define TUN_SOCKET__LISTEN 0x00001000UL
+#define TUN_SOCKET__ACCEPT 0x00002000UL
+#define TUN_SOCKET__GETOPT 0x00004000UL
+#define TUN_SOCKET__SETOPT 0x00008000UL
+#define TUN_SOCKET__SHUTDOWN 0x00010000UL
+#define TUN_SOCKET__RECVFROM 0x00020000UL
+#define TUN_SOCKET__SENDTO 0x00040000UL
+#define TUN_SOCKET__RECV_MSG 0x00080000UL
+#define TUN_SOCKET__SEND_MSG 0x00100000UL
+#define TUN_SOCKET__NAME_BIND 0x00200000UL
#define PROCESS__FORK 0x00000001UL
#define PROCESS__TRANSITION 0x00000002UL
#define PROCESS__SIGCHLD 0x00000004UL
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
index 21ec786..7ab9299 100644
--- a/security/selinux/include/class_to_string.h
+++ b/security/selinux/include/class_to_string.h
@@ -77,3 +77,4 @@
S_(NULL)
S_(NULL)
S_("kernel_service")
+ S_("tun_socket")
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h
index 882f27d..f248500 100644
--- a/security/selinux/include/flask.h
+++ b/security/selinux/include/flask.h
@@ -53,6 +53,7 @@
#define SECCLASS_PEER 68
#define SECCLASS_CAPABILITY2 69
#define SECCLASS_KERNEL_SERVICE 74
+#define SECCLASS_TUN_SOCKET 75
/*
* Security identifier indices for initial entities
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index ca83579..188af8d 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -63,12 +63,14 @@ extern int selinux_mls_enabled;
enum {
POLICYDB_CAPABILITY_NETPEER,
POLICYDB_CAPABILITY_OPENPERM,
+ POLICYDB_CAPABILITY_TUNPERM,
__POLICYDB_CAPABILITY_MAX
};
#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
extern int selinux_policycap_netpeer;
extern int selinux_policycap_openperm;
+extern int selinux_policycap_tunperm;
/*
* type_datum properties
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index b4fc506..770e059 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -42,7 +42,8 @@
/* Policy capability filenames */
static char *policycap_names[] = {
"network_peer_controls",
- "open_perms"
+ "open_perms",
+ "tun_perms"
};
unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 500e6f7..adbe6d5 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -64,6 +64,7 @@ unsigned int policydb_loaded_version;
int selinux_policycap_netpeer;
int selinux_policycap_openperm;
+int selinux_policycap_tunperm;
/*
* This is declared in avc.c
@@ -1593,6 +1594,8 @@ static void security_load_policycaps(void)
POLICYDB_CAPABILITY_NETPEER);
selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
POLICYDB_CAPABILITY_OPENPERM);
+ selinux_policycap_tunperm = ebitmap_get_bit(&policydb.policycaps,
+ POLICYDB_CAPABILITY_TUNPERM);
}
extern void selinux_complete_init(void);
^ permalink raw reply related
* [PATCH 6/5] cpmac: unmark as broken
From: Florian Fainelli @ 2009-08-04 21:17 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, netdev, David Miller
Hi David,
I realised afterwards that unmarking cpmac as BROKEN
should have been part of the previous patch series that I sent.
Sorry about that.
--
From: Florian Fainelli <florian@openwrt.org>
Subject: [PATCH 6/5] cpmac: unmark as broken
Starting with version 0.5.1, cpmac is no longer broken.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5f6509a..9948fa2 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1774,7 +1774,7 @@ config SC92031
config CPMAC
tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)"
- depends on NET_ETHERNET && EXPERIMENTAL && AR7 && BROKEN
+ depends on NET_ETHERNET && EXPERIMENTAL && AR7
select PHYLIB
help
TI AR7 CPMAC Ethernet support
^ permalink raw reply related
* Re: [PATCH 5/5] c/r: Add AF_UNIX support (v7)
From: Serge E. Hallyn @ 2009-08-04 21:17 UTC (permalink / raw)
To: Dan Smith; +Cc: containers, Alexey Dobriyan, netdev
In-Reply-To: <878whzl2cs.fsf@caffeine.danplanet.com>
Quoting Dan Smith (danms@us.ibm.com):
> SH> Does this re-use of tmp make sense? (It only would if
> SH> dev_alloc_skb() did a generic prealloc for any subsequent
> SH> skb_clone() which i don't think is the case)
>
> No, this is cruft.
>
> SH> Also, do you need any kind of lock on the queue to make this walk
> SH> safe, or do ensure below (sorry i'm slow and haven't gotten there)
> SH> that all tasks with an open fd for either end of this sock are
> SH> frozen?
>
> Hmm, it seems that holding the lock while processing the queue isn't
> really the way to go. Perhaps comparing the pid of the other end of
> the socket against the list in the context is best?
I don't understand. Which pid?
^ permalink raw reply
* Re: [PATCH 5/5] c/r: Add AF_UNIX support (v7)
From: Dan Smith @ 2009-08-04 21:02 UTC (permalink / raw)
To: Serge E. Hallyn; +Cc: containers, Alexey Dobriyan, netdev
In-Reply-To: <20090804205241.GF10275@us.ibm.com>
SH> Does this re-use of tmp make sense? (It only would if
SH> dev_alloc_skb() did a generic prealloc for any subsequent
SH> skb_clone() which i don't think is the case)
No, this is cruft.
SH> Also, do you need any kind of lock on the queue to make this walk
SH> safe, or do ensure below (sorry i'm slow and haven't gotten there)
SH> that all tasks with an open fd for either end of this sock are
SH> frozen?
Hmm, it seems that holding the lock while processing the queue isn't
really the way to go. Perhaps comparing the pid of the other end of
the socket against the list in the context is best?
SH> what about UNIXCB(skb).creds and .secid?
Yep, okay.
SH> It looks like the above provides a way around needing
SH> CAP_NET_ADMIN to set SOCK_DBG in sock->sk_flags? You can probably
SH> fix that by masking it out here, and if a flag in the checkpoint
SH> image says it was on originally, then set it below through
SH> setsockopt.
Yep, okay.
SH> Sanity checking on sk_type, sk_state, backlog etc should probably
SH> also be added.
I check type and state on restart globally and per-protocol. Backlog
could use it though too, yeah.
Thanks!
--
Dan Smith
IBM Linux Technology Center
email: danms@us.ibm.com
^ permalink raw reply
* [PATCH 4/5] cpmac: wait longer after MDIO reset
From: Florian Fainelli @ 2009-08-04 20:52 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, netdev, David Miller
This patch slows down the MDIO_ALIVE busy waiting to let
switches and PHY come up after reset. Previous loop was
too quick for IC+175C and ADM6996C/L switches to come up.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index f2fc722..12a521e 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -1245,11 +1245,11 @@ int __devinit cpmac_init(void)
cpmac_mii->reset(cpmac_mii);
- for (i = 0; i < 300000; i++)
+ for (i = 0; i < 300; i++)
if ((mask = cpmac_read(cpmac_mii->priv, CPMAC_MDIO_ALIVE)))
break;
else
- cpu_relax();
+ msleep(10);
mask &= 0x7fffffff;
if (mask & (mask - 1)) {
^ permalink raw reply related
* [PATCH 5/5] cpmac: bump version to 0.5.1
From: Florian Fainelli @ 2009-08-04 20:53 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, netdev, David Miller
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index 12a521e..0ef7467 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -54,7 +54,7 @@ module_param(dumb_switch, int, 0444);
MODULE_PARM_DESC(debug_level, "Number of NETIF_MSG bits to enable");
MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus");
-#define CPMAC_VERSION "0.5.0"
+#define CPMAC_VERSION "0.5.1"
/* frame size + 802.1q tag */
#define CPMAC_SKB_SIZE (ETH_FRAME_LEN + 4)
#define CPMAC_QUEUES 8
^ permalink raw reply related
* [PATCH 3/5] cpmac: add support for fixed PHY
From: Florian Fainelli @ 2009-08-04 20:52 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, netdev, David Miller
This patch adds support for fixed PHY connected in MII mode
to cpmac. We allow external and dumb_switch module parameters
to override the PHY detection process since they are always connected
with MDIO bus identifier 0. This lets fixed PHYs to be detected
correctly and be connected to the their corresponding MDIO
bus identifier.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index c951dd4..f2fc722 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -1117,22 +1117,23 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
pdata = pdev->dev.platform_data;
- for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
- if (!(pdata->phy_mask & (1 << phy_id)))
- continue;
- if (!cpmac_mii->phy_map[phy_id])
- continue;
- break;
+ if (external_switch || dumb_switch) {
+ strncpy(mdio_bus_id, "0", BUS_ID_SIZE); /* fixed phys bus */
+ phy_id = pdev->id;
+ } else {
+ for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
+ if (!(pdata->phy_mask & (1 << phy_id)))
+ continue;
+ if (!cpmac_mii->phy_map[phy_id])
+ continue;
+ strncpy(mdio_bus_id, cpmac_mii->id, BUS_ID_SIZE);
+ break;
+ }
}
if (phy_id == PHY_MAX_ADDR) {
- if (external_switch || dumb_switch) {
- strncpy(mdio_bus_id, "0", BUS_ID_SIZE); /* fixed phys bus */
- phy_id = pdev->id;
- } else {
- dev_err(&pdev->dev, "no PHY present\n");
- return -ENODEV;
- }
+ dev_err(&pdev->dev, "no PHY present\n");
+ return -ENODEV;
}
dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES);
@@ -1166,8 +1167,11 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
priv->msg_enable = netif_msg_init(debug_level, 0xff);
memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr));
- priv->phy = phy_connect(dev, dev_name(&cpmac_mii->phy_map[phy_id]->dev),
- &cpmac_adjust_link, 0, PHY_INTERFACE_MODE_MII);
+ snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
+
+ priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0,
+ PHY_INTERFACE_MODE_MII);
+
if (IS_ERR(priv->phy)) {
if (netif_msg_drv(priv))
printk(KERN_ERR "%s: Could not attach to PHY\n",
^ permalink raw reply related
* Re: [PATCH 5/5] c/r: Add AF_UNIX support (v7)
From: Serge E. Hallyn @ 2009-08-04 20:52 UTC (permalink / raw)
To: Dan Smith; +Cc: containers, Alexey Dobriyan, netdev
In-Reply-To: <1249331463-11887-6-git-send-email-danms@us.ibm.com>
Quoting Dan Smith (danms@us.ibm.com):
...
> +static int sock_copy_buffers(struct sk_buff_head *from,
> + struct sk_buff_head *to,
> + uint32_t *total_bytes)
> +{
> + int count = 0;
> + struct sk_buff *skb;
> +
> + *total_bytes = 0;
> +
> + skb_queue_walk(from, skb) {
> + struct sk_buff *tmp;
> +
> + tmp = dev_alloc_skb(skb->len);
> + if (!tmp)
> + return -ENOMEM;
> +
> + spin_lock(&from->lock);
> + tmp = skb_clone(skb, GFP_KERNEL);
Does this re-use of tmp make sense? (It only would if dev_alloc_skb()
did a generic prealloc for any subsequent skb_clone() which i don't think
is the case)
Also, do you need any kind of lock on the queue to make this
walk safe, or do ensure below (sorry i'm slow and haven't gotten
there) that all tasks with an open fd for either end of this
sock are frozen?
> + spin_unlock(&from->lock);
> +
> + skb_queue_tail(to, tmp);
> + count++;
> + *total_bytes += tmp->len;
> + }
> +
> + return count;
> +}
> +
> +static int __sock_write_buffers(struct ckpt_ctx *ctx,
> + struct sk_buff_head *queue)
> +{
> + struct sk_buff *skb;
> + int ret = 0;
> +
> + skb_queue_walk(queue, skb) {
> + if (UNIXCB(skb).fp) {
> + ckpt_write_err(ctx, "fd-passing is not supported");
> + return -EBUSY;
> + }
what about UNIXCB(skb).creds and .secid?
> + ret = ckpt_write_obj_type(ctx, skb->data, skb->len,
> + CKPT_HDR_SOCKET_BUFFER);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int sock_write_buffers(struct ckpt_ctx *ctx, struct sk_buff_head *queue)
> +{
> + struct ckpt_hdr_socket_queue *h;
> + struct sk_buff_head tmpq;
> + int ret = -ENOMEM;
> +
> + h = ckpt_hdr_get_type(ctx, sizeof(*h), CKPT_HDR_SOCKET_QUEUE);
> + if (!h)
> + goto out;
Again, you can't ckpt_hdr_put with a NULL h.
> + skb_queue_head_init(&tmpq);
> +
> + ret = sock_copy_buffers(queue, &tmpq, &h->total_bytes);
> + if (ret < 0)
> + goto out;
> +
> + h->skb_count = ret;
> + ret = ckpt_write_obj(ctx, (struct ckpt_hdr *) h);
> + if (!ret)
> + ret = __sock_write_buffers(ctx, &tmpq);
> +
> + out:
> + ckpt_hdr_put(ctx, h);
> + __skb_queue_purge(&tmpq);
> +
> + return ret;
> +}
> +
> +static int sock_unix_write_cwd(struct ckpt_ctx *ctx,
> + struct sock *sock,
> + const char *sockpath)
> +{
> + struct path path;
> + char *buf;
> + char *fqpath;
> + int offset;
> + int len = PATH_MAX;
> + int ret = -ENOENT;
> +
> + buf = kmalloc(PATH_MAX, GFP_KERNEL);
sending len to kmalloc instead of PATH_MAX might be more future-proof...
> + if (!buf)
> + return -ENOMEM;
> +
> + path.dentry = unix_sk(sock)->dentry;
> + path.mnt = unix_sk(sock)->mnt;
> +
> + fqpath = ckpt_fill_fname(&path, &ctx->fs_mnt, buf, &len);
> + if (IS_ERR(fqpath)) {
> + ret = PTR_ERR(fqpath);
> + goto out;
> + }
> +
> + offset = strlen(fqpath) - strlen(sockpath);
> + if (offset <= 0) {
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + fqpath[offset] = '\0';
> +
> + ckpt_debug("writing socket directory: %s\n", fqpath);
> + ret = ckpt_write_string(ctx, fqpath, strlen(fqpath));
> + out:
> + kfree(buf);
> + return ret;
> +}
looks good.
> +static int sock_getnames(struct ckpt_ctx *ctx,
> + struct socket *socket,
> + struct sockaddr *loc, unsigned *loc_len,
> + struct sockaddr *rem, unsigned *rem_len)
> +{
> + if (sock_getname(socket, loc, loc_len)) {
> + ckpt_write_err(ctx, "Unable to getname of local");
maybe log the errno?
> + return -EINVAL;
> + }
> +
> + if (sock_getpeer(socket, rem, rem_len)) {
> + if ((socket->sk->sk_type != SOCK_DGRAM) &&
> + (socket->sk->sk_state == TCP_ESTABLISHED)) {
> + ckpt_write_err(ctx, "Unable to getname of remote");
> + return -EINVAL;
> + }
> + *rem_len = 0;
> + }
> +
> + return 0;
> +}
> +
> +static int sock_unix_checkpoint(struct ckpt_ctx *ctx,
> + struct socket *socket,
> + struct ckpt_hdr_socket *h)
> +{
> + struct unix_sock *sk = unix_sk(socket->sk);
> + struct unix_sock *pr = unix_sk(sk->peer);
> + struct ckpt_hdr_socket_unix *un;
> + int new;
> + int ret = -ENOMEM;
> +
> + if ((socket->sk->sk_state == TCP_LISTEN) &&
> + !skb_queue_empty(&socket->sk->sk_receive_queue)) {
> + ckpt_write_err(ctx, "listening socket has unaccepted peers");
> + return -EBUSY;
> + }
> +
> + un = ckpt_hdr_get_type(ctx, sizeof(*un), CKPT_HDR_SOCKET_UNIX);
> + if (!un)
> + goto out;
> +
> + ret = sock_getnames(ctx, socket,
> + (struct sockaddr *)&un->laddr, &un->laddr_len,
> + (struct sockaddr *)&un->raddr, &un->raddr_len);
> + if (ret)
> + goto out;
> +
> + if (sk->dentry && (sk->dentry->d_inode->i_nlink > 0))
> + un->flags |= CKPT_UNIX_LINKED;
> +
> + un->this = ckpt_obj_lookup_add(ctx, sk, CKPT_OBJ_SOCK, &new);
> + if (un->this < 0)
> + goto out;
> +
> + if (sk->peer)
> + un->peer = ckpt_obj_lookup_add(ctx, pr, CKPT_OBJ_SOCK, &new);
> + else
> + un->peer = 0;
> +
> + if (un->peer < 0) {
> + ret = un->peer;
> + goto out;
> + }
> +
> + ret = ckpt_write_obj(ctx, (struct ckpt_hdr *) h);
> + if (ret < 0)
> + goto out;
> +
> + ret = ckpt_write_obj(ctx, (struct ckpt_hdr *) un);
> + if (ret < 0)
> + goto out;
> +
> + if (sock_unix_need_cwd(&un->laddr, un->laddr_len))
> + ret = sock_unix_write_cwd(ctx, socket->sk, un->laddr.sun_path);
> + out:
> + ckpt_hdr_put(ctx, un);
> +
> + return ret;
> +}
> +
> +static int sock_cptrst_verify(struct ckpt_hdr_socket *h)
> +{
> + uint8_t userlocks_mask = SOCK_SNDBUF_LOCK | SOCK_RCVBUF_LOCK |
> + SOCK_BINDADDR_LOCK | SOCK_BINDPORT_LOCK;
> +
> + if (h->sock.shutdown & ~SHUTDOWN_MASK)
> + return -EINVAL;
> + if (h->sock.userlocks & ~userlocks_mask)
> + return -EINVAL;
> + if (!ckpt_validate_errno(h->sock.err))
> + return -EINVAL;
> +
> + /* None of our supported types use this flag */
> + if (h->sock.flags & SOCK_DESTROY)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +static int sock_cptrst_opt(int op, struct socket *socket,
> + int optname, char *opt, int len)
> +{
> + mm_segment_t fs;
> + int ret;
> +
> + fs = get_fs();
> + set_fs(KERNEL_DS);
> +
> + if (op == CKPT_CPT)
> + ret = sock_getsockopt(socket, SOL_SOCKET, optname, opt, &len);
> + else
> + ret = sock_setsockopt(socket, SOL_SOCKET, optname, opt, len);
> +
> + set_fs(fs);
> +
> + return ret;
> +}
> +
> +#define CKPT_COPY_SOPT(op, sock, name, opt) \
> + sock_cptrst_opt(op, sock->sk_socket, name, (char *)opt, sizeof(*opt))
> +
> +static int sock_cptrst_bufopts(int op, struct sock *sock,
> + struct ckpt_hdr_socket *h)
> +
> +{
> + if (CKPT_COPY_SOPT(op, sock, SO_RCVBUF, &h->sock.rcvbuf))
> + if ((op == CKPT_RST) &&
> + CKPT_COPY_SOPT(op, sock, SO_RCVBUFFORCE, &h->sock.rcvbuf)) {
> + ckpt_debug("Failed to set SO_RCVBUF");
> + return -EINVAL;
> + }
> +
> + if (CKPT_COPY_SOPT(op, sock, SO_SNDBUF, &h->sock.sndbuf))
> + if ((op == CKPT_RST) &&
> + CKPT_COPY_SOPT(op, sock, SO_SNDBUFFORCE, &h->sock.sndbuf)) {
> + ckpt_debug("Failed to set SO_SNDBUF");
> + return -EINVAL;
> + }
> +
> + /* It's silly that we have to fight ourselves here, but
> + * sock_setsockopt() doubles the initial value, so divide here
> + * to store the user's value and avoid doubling on restart
> + */
> + if ((op == CKPT_CPT) && (h->sock.rcvbuf != SOCK_MIN_RCVBUF))
> + h->sock.rcvbuf >>= 1;
> +
> + if ((op == CKPT_CPT) && (h->sock.sndbuf != SOCK_MIN_SNDBUF))
> + h->sock.sndbuf >>= 1;
> +
> + return 0;
> +}
> +
> +static int sock_cptrst(struct ckpt_ctx *ctx,
> + struct sock *sock,
> + struct ckpt_hdr_socket *h,
> + int op)
> +{
> + if (sock->sk_socket) {
> + CKPT_COPY(op, h->socket.flags, sock->sk_socket->flags);
> + CKPT_COPY(op, h->socket.state, sock->sk_socket->state);
> + }
> +
> + CKPT_COPY(op, h->sock_common.bound_dev_if, sock->sk_bound_dev_if);
> + CKPT_COPY(op, h->sock_common.family, sock->sk_family);
> +
> + CKPT_COPY(op, h->sock.shutdown, sock->sk_shutdown);
> + CKPT_COPY(op, h->sock.userlocks, sock->sk_userlocks);
> + CKPT_COPY(op, h->sock.no_check, sock->sk_no_check);
> + CKPT_COPY(op, h->sock.protocol, sock->sk_protocol);
> + CKPT_COPY(op, h->sock.err, sock->sk_err);
> + CKPT_COPY(op, h->sock.err_soft, sock->sk_err_soft);
> + CKPT_COPY(op, h->sock.backlog, sock->sk_max_ack_backlog);
> + CKPT_COPY(op, h->sock.flags, sock->sk_flags);
> + CKPT_COPY(op, h->sock.type, sock->sk_type);
> + CKPT_COPY(op, h->sock.state, sock->sk_state);
It looks like the above provides a way around needing CAP_NET_ADMIN
to set SOCK_DBG in sock->sk_flags? You can probably fix that by
masking it out here, and if a flag in the checkpoint image says
it was on originally, then set it below through setsockopt.
Sanity checking on sk_type, sk_state, backlog etc should probably also be
added.
I do like how you re-use setsockopt below to maintain security
and sanity checks on those fields.
> +
> + if (sock_cptrst_bufopts(op, sock, h))
> + return -EINVAL;
> +
> + if (CKPT_COPY_SOPT(op, sock, SO_REUSEADDR, &h->sock_common.reuse)) {
> + ckpt_debug("Failed to set SO_REUSEADDR");
> + return -EINVAL;
> + }
> +
> + if (CKPT_COPY_SOPT(op, sock, SO_PRIORITY, &h->sock.priority)) {
> + ckpt_debug("Failed to set SO_PRIORITY");
> + return -EINVAL;
> + }
> +
> + if (CKPT_COPY_SOPT(op, sock, SO_RCVLOWAT, &h->sock.rcvlowat)) {
> + ckpt_debug("Failed to set SO_RCVLOWAT");
> + return -EINVAL;
> + }
> +
> + if (CKPT_COPY_SOPT(op, sock, SO_LINGER, &h->sock.linger)) {
> + ckpt_debug("Failed to set SO_LINGER");
> + return -EINVAL;
> + }
> +
> + if (CKPT_COPY_SOPT(op, sock, SO_SNDTIMEO, &h->sock.sndtimeo)) {
> + ckpt_debug("Failed to set SO_SNDTIMEO");
> + return -EINVAL;
> + }
> +
> + if (CKPT_COPY_SOPT(op, sock, SO_RCVTIMEO, &h->sock.rcvtimeo)) {
> + ckpt_debug("Failed to set SO_RCVTIMEO");
> + return -EINVAL;
> + }
> +
> + if ((h->socket.state == SS_CONNECTED) &&
> + (h->sock.state != TCP_ESTABLISHED)) {
> + ckpt_debug("socket/sock in inconsistent state: %i/%i",
> + h->socket.state, h->sock.state);
> + return -EINVAL;
> + } else if ((h->sock.state < TCP_ESTABLISHED) ||
> + (h->sock.state >= TCP_MAX_STATES)) {
> + ckpt_debug("sock in invalid state: %i", h->sock.state);
> + return -EINVAL;
> + } else if ((h->socket.state < SS_FREE) ||
> + (h->socket.state > SS_DISCONNECTING)) {
> + ckpt_debug("socket in invalid state: %i",
> + h->socket.state);
> + return -EINVAL;
> + }
> +
> + if (op == CKPT_CPT)
> + return sock_cptrst_verify(h);
> + else
> + return 0;
> +}
> +
> +int do_sock_file_checkpoint(struct ckpt_ctx *ctx, struct file *file)
> +{
> + struct socket *socket = file->private_data;
> + struct sock *sock = socket->sk;
> + struct ckpt_hdr_socket *h;
> + int ret = 0;
> +
> + h = ckpt_hdr_get_type(ctx, sizeof(*h), CKPT_HDR_SOCKET);
> + if (!h)
> + return -ENOMEM;
> +
> + ret = sock_cptrst(ctx, sock, h, CKPT_CPT);
> + if (ret)
> + goto out;
> +
> + if (sock->sk_family == AF_UNIX) {
> + ret = sock_unix_checkpoint(ctx, socket, h);
> + if (ret)
> + goto out;
> + } else {
> + ckpt_write_err(ctx, "unsupported socket family %i",
> + sock->sk_family);
> + ret = -ENOSYS;
> + goto out;
> + }
> +
> + if (sock->sk_state != TCP_LISTEN) {
> + ret = sock_write_buffers(ctx, &sock->sk_receive_queue);
> + if (ret)
> + goto out;
> +
> + ret = sock_write_buffers(ctx, &sock->sk_write_queue);
> + if (ret)
> + goto out;
> + }
> + out:
> + ckpt_hdr_put(ctx, h);
> +
> + return ret;
> +}
> +
(will go on from here later :)
-serge
^ permalink raw reply
* [PATCH 2/5] ar7: add fixed PHY support for the two on-board cpmac
From: Florian Fainelli @ 2009-08-04 20:52 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, netdev, David Miller
This patch adds fixed PHY support for the two on-chip
cpmac Ethernet adapters.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/arch/mips/ar7/platform.c b/arch/mips/ar7/platform.c
index 5422449..c4737ce 100644
--- a/arch/mips/ar7/platform.c
+++ b/arch/mips/ar7/platform.c
@@ -33,6 +33,8 @@
#include <linux/leds.h>
#include <linux/string.h>
#include <linux/etherdevice.h>
+#include <linux/phy.h>
+#include <linux/phy_fixed.h>
#include <asm/addrspace.h>
#include <asm/mach-ar7/ar7.h>
@@ -209,6 +211,12 @@ static struct physmap_flash_data physmap_flash_data = {
.width = 2,
};
+static struct fixed_phy_status fixed_phy_status __initdata = {
+ .link = 1,
+ .speed = 100,
+ .duplex = 1,
+};
+
static struct plat_cpmac_data cpmac_low_data = {
.reset_bit = 17,
.power_bit = 20,
@@ -530,6 +538,9 @@ static int __init ar7_register_devices(void)
}
if (ar7_has_high_cpmac()) {
+ res = fixed_phy_add(PHY_POLL, cpmac_high.id, &fixed_phy_status);
+ if (res && res != -ENODEV)
+ return res;
cpmac_get_mac(1, cpmac_high_data.dev_addr);
res = platform_device_register(&cpmac_high);
if (res)
@@ -538,6 +549,10 @@ static int __init ar7_register_devices(void)
cpmac_low_data.phy_mask = 0xffffffff;
}
+ res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status);
+ if (res && res != -ENODEV)
+ return res;
+
cpmac_get_mac(0, cpmac_low_data.dev_addr);
res = platform_device_register(&cpmac_low);
if (res)
^ permalink raw reply related
* [PATCH 1/5] cpmac: fix wrong MDIO bus identifier
From: Florian Fainelli @ 2009-08-04 20:52 UTC (permalink / raw)
To: Ralf Baechle; +Cc: linux-mips, netdev, David Miller
This patch fixes the wrong MDIO bus identifier which was
set to 0 unconditionaly, suitable for external switches while
it is actually 1 for PHYs different than external switches
which are autodetected.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index fd5e32c..c951dd4 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -1109,7 +1109,7 @@ static int external_switch;
static int __devinit cpmac_probe(struct platform_device *pdev)
{
int rc, phy_id;
- char *mdio_bus_id = "0";
+ char mdio_bus_id[BUS_ID_SIZE];
struct resource *mem;
struct cpmac_priv *priv;
struct net_device *dev;
@@ -1127,7 +1127,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
if (phy_id == PHY_MAX_ADDR) {
if (external_switch || dumb_switch) {
- mdio_bus_id = 0; /* fixed phys bus */
+ strncpy(mdio_bus_id, "0", BUS_ID_SIZE); /* fixed phys bus */
phy_id = pdev->id;
} else {
dev_err(&pdev->dev, "no PHY present\n");
@@ -1254,7 +1254,7 @@ int __devinit cpmac_init(void)
}
cpmac_mii->phy_mask = ~(mask | 0x80000000);
- snprintf(cpmac_mii->id, MII_BUS_ID_SIZE, "0");
+ snprintf(cpmac_mii->id, MII_BUS_ID_SIZE, "1");
res = mdiobus_register(cpmac_mii);
if (res)
^ permalink raw reply related
* [PATCH] netxen: fix dma mask update calculation
From: Dhananjay Phadke @ 2009-08-04 20:39 UTC (permalink / raw)
To: davem; +Cc: netdev
Fix dma mask calculation that caps at 63-bit addressing even
when firmware advertises full 64-bit support.
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
---
drivers/net/netxen/netxen_nic_main.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 3cd8cfc..70c05c4 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -260,7 +260,7 @@ nx_update_dma_mask(struct netxen_adapter *adapter)
change = 0;
shift = NXRD32(adapter, CRB_DMA_SHIFT);
- if (shift >= 32)
+ if (shift > 32)
return 0;
if (NX_IS_REVISION_P3(adapter->ahw.revision_id) && (shift > 9))
@@ -272,7 +272,7 @@ nx_update_dma_mask(struct netxen_adapter *adapter)
old_mask = pdev->dma_mask;
old_cmask = pdev->dev.coherent_dma_mask;
- mask = (1ULL<<(32+shift)) - 1;
+ mask = DMA_BIT_MASK(32+shift);
err = pci_set_dma_mask(pdev, mask);
if (err)
--
1.6.0.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox