Commit 90a880a4 authored by Linus Torvalds's avatar Linus Torvalds

v2.4.2.6 -> v2.4.2.7

  - more bugs found by the automatic stanford checker, yay!
  - Andrew Morton: fix SAK locking bugs by moving it into a process context
  - Johannes Erdfelt: USB updates
  - Jeff Garzik: merge Hermes driver by David Gibson
  - Jens Axboe: cdrom merges, ll_rw_blk proper accounting
parent 94540b50
......@@ -7474,6 +7474,18 @@ CONFIG_NET_PCMCIA_RADIO
location). You also want to check out the PCMCIA-HOWTO, available
from http://www.linuxdoc.org/docs.html#howto .
Hermes (AT&T/Lucent/Orinoco/3com) wireless support
CONFIG_PCMCIA_HERMES
A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
as the Lucent/Orinoco cards and the Cabletron RoamAbout. It should
also be usable on Prism II based cards such as the Farallon Skyline
and the 3Com AirConnect.
To use your PC-cards, you will need supporting software from David
Hinds' pcmcia-cs package (see the file Documentation/Changes for
location). You also want to check out the PCMCIA-HOWTO, available
from http://www.linuxdoc.org/docs.html#howto .
Aviator/Raytheon 2.4MHz wireless support
CONFIG_PCMCIA_RAYCS
Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
......
Linux 2.4.2 Secure Attention Key (SAK) handling
18 March 2001, Andrew Morton <andrewm@uow.edu.au>
An operating system's Secure Attention Key is a security tool which is
provided as protection against trojan password capturing programs. It
is an undefeatable way of killing all programs which could be
masquerading as login applications. Users need to be taught to enter
this key sequence before they log in to the system.
From the PC keyboard, Linux has two similar but different ways of
providing SAK. One is the ALT-SYSRQ-K sequence. You shouldn't use
this sequence. It is only available if the kernel was compiled with
sysrq support.
The proper way of generating a SAK is to define the key sequence using
`loadkeys'. This will work whether or not sysrq support is compiled
into the kernel.
SAK works correctly when the keyboard is in raw mode. This means that
once defined, SAK will kill a running X server. If the system is in
run level 5, the X server will restart. This is what you want to
happen.
What key sequence should you use? Well, CTRL-ALT-DEL is used to reboot
the machine. CTRL-ALT-BACKSPACE is magical to the X server. We'll
choose CTRL-ALT-PAUSE.
In your rc.sysinit (or rc.local) file, add the command
echo "control alt keycode 101 = SAK" | /bin/loadkeys
And that's it! Only the superuser may reprogram the SAK key.
NOTES
=====
1: Linux SAK is said to be not a "true SAK" as is required by
systems which implement C2 level security. This author does not
know why.
2: On the PC keyboard, SAK kills all applications which have
/dev/console opened.
Unfortunately this includes a number of things which you don't
actually want killed. This is because these appliccaitons are
incorrectly holding /dev/console open. Be sure to complain to your
Linux distributor about this!
You can identify processes which will be killed by SAK with the
command
# ls -l /proc/[0-9]*/fd/* | grep console
l-wx------ 1 root root 64 Mar 18 00:46 /proc/579/fd/0 -> /dev/console
Then:
# ps aux|grep 579
root 579 0.0 0.1 1088 436 ? S 00:43 0:00 gpm -t ps/2
So `gpm' will be killed by SAK. This is a bug in gpm. It should
be closing standard input. You can work around this by finding the
initscript which launches gpm and changing it thusly:
Old:
daemon gpm
New:
daemon gpm < /dev/null
Vixie cron also seems to have this problem, and needs the same treatment.
Also, one prominent Linux distribution has the following three
lines in its rc.sysinit and rc scripts:
exec 3<&0
exec 4>&1
exec 5>&2
These commands cause *all* daemons which are launched by the
initscripts to have file descriptors 3, 4 and 5 attached to
/dev/console. So SAK kills them all. A workaround is to simply
delete these lines, but this may cause system management
applications to malfunction - test everything well.
......@@ -29,6 +29,8 @@ On the serial console (PC style standard serial ports only) -
You send a BREAK, then within 5 seconds a command key. Sending
BREAK twice is interpreted as a normal BREAK.
On Mac - Press 'Keypad+-F13-<command key>'
On other - If you know of the key combos for other architectures, please
let me know so I can add them to this section.
......
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 3
EXTRAVERSION =-pre6
EXTRAVERSION =-pre7
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
......
......@@ -434,6 +434,7 @@ CONFIG_PCMCIA_PCNET=y
# CONFIG_PCMCIA_XIRTULIP is not set
CONFIG_NET_PCMCIA_RADIO=y
CONFIG_PCMCIA_RAYCS=y
# CONFIG_PCMCIA_HERMES is not set
# CONFIG_PCMCIA_NETWAVE is not set
# CONFIG_PCMCIA_WAVELAN is not set
# CONFIG_AIRONET4500_CS is not set
......
......@@ -204,7 +204,6 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm)
for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
if (bprm->page[i]) {
current->mm->rss++;
put_dirty_page(current,bprm->page[i],stack_base);
}
stack_base += PAGE_SIZE;
......
......@@ -73,7 +73,6 @@ int setup_arg_pages32(struct linux_binprm *bprm)
struct page *page = bprm->page[i];
if (page) {
bprm->page[i] = NULL;
current->mm->rss++;
put_dirty_page(current,page,stack_base);
}
stack_base += PAGE_SIZE;
......
......@@ -954,6 +954,8 @@ void generic_make_request (int rw, struct buffer_head * bh)
*/
void submit_bh(int rw, struct buffer_head * bh)
{
int count = bh->b_size >> 9;
if (!test_bit(BH_Lock, &bh->b_state))
BUG();
......@@ -964,16 +966,16 @@ void submit_bh(int rw, struct buffer_head * bh)
* further remap this.
*/
bh->b_rdev = bh->b_dev;
bh->b_rsector = bh->b_blocknr * (bh->b_size >> 9);
bh->b_rsector = bh->b_blocknr * count;
generic_make_request(rw, bh);
switch (rw) {
case WRITE:
kstat.pgpgout++;
kstat.pgpgout += count;
break;
default:
kstat.pgpgin++;
kstat.pgpgin += count;
break;
}
}
......
......@@ -1171,42 +1171,50 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
{
int ret, i;
u_char buf[4 + 4 * 20], *base;
unsigned char buf[20], *base;
struct dvd_layer *layer;
struct cdrom_generic_command cgc;
struct cdrom_device_ops *cdo = cdi->ops;
int ret, layer_num = s->physical.layer_num;
if (layer_num >= DVD_LAYERS)
return -EINVAL;
init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[6] = s->physical.layer_num;
cgc.cmd[6] = layer_num;
cgc.cmd[7] = s->type;
cgc.cmd[9] = cgc.buflen & 0xff;
/*
* refrain from reporting errors on non-existing layers (mainly)
*/
cgc.quiet = 1;
if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret;
base = &buf[4];
layer = &s->physical.layer[0];
/* place the data... really ugly, but at least we won't have to
worry about endianess in userspace or here. */
for (i = 0; i < 4; ++i, base += 20, ++layer) {
memset(layer, 0, sizeof(*layer));
layer->book_version = base[0] & 0xf;
layer->book_type = base[0] >> 4;
layer->min_rate = base[1] & 0xf;
layer->disc_size = base[1] >> 4;
layer->layer_type = base[2] & 0xf;
layer->track_path = (base[2] >> 4) & 1;
layer->nlayers = (base[2] >> 5) & 3;
layer->track_density = base[3] & 0xf;
layer->linear_density = base[3] >> 4;
layer->start_sector = base[5] << 16 | base[6] << 8 | base[7];
layer->end_sector = base[9] << 16 | base[10] << 8 | base[11];
layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15];
layer->bca = base[16] >> 7;
}
layer = &s->physical.layer[layer_num];
/*
* place the data... really ugly, but at least we won't have to
* worry about endianess in userspace.
*/
memset(layer, 0, sizeof(*layer));
layer->book_version = base[0] & 0xf;
layer->book_type = base[0] >> 4;
layer->min_rate = base[1] & 0xf;
layer->disc_size = base[1] >> 4;
layer->layer_type = base[2] & 0xf;
layer->track_path = (base[2] >> 4) & 1;
layer->nlayers = (base[2] >> 5) & 3;
layer->track_density = base[3] & 0xf;
layer->linear_density = base[3] >> 4;
layer->start_sector = base[5] << 16 | base[6] << 8 | base[7];
layer->end_sector = base[9] << 16 | base[10] << 8 | base[11];
layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15];
layer->bca = base[16] >> 7;
return 0;
}
......@@ -1985,7 +1993,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
}
case CDROMREADAUDIO: {
struct cdrom_read_audio ra;
int lba;
int lba, nr;
IOCTL_IN(arg, struct cdrom_read_audio, ra);
......@@ -2002,7 +2010,19 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
if (lba < 0 || ra.nframes <= 0)
return -EINVAL;
if ((cgc.buffer = (char *) kmalloc(CD_FRAMESIZE_RAW, GFP_KERNEL)) == NULL)
/*
* start with will ra.nframes size, back down if alloc fails
*/
nr = ra.nframes;
do {
cgc.buffer = kmalloc(CD_FRAMESIZE_RAW * nr, GFP_KERNEL);
if (cgc.buffer)
break;
nr >>= 1;
} while (nr);
if (!nr)
return -ENOMEM;
if (!access_ok(VERIFY_WRITE, ra.buf, ra.nframes*CD_FRAMESIZE_RAW)) {
......@@ -2011,12 +2031,16 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
}
cgc.data_direction = CGC_DATA_READ;
while (ra.nframes > 0) {
ret = cdrom_read_block(cdi, &cgc, lba, 1, 1, CD_FRAMESIZE_RAW);
if (ret) break;
if (nr > ra.nframes)
nr = ra.nframes;
ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW);
if (ret)
break;
__copy_to_user(ra.buf, cgc.buffer, CD_FRAMESIZE_RAW);
ra.buf += CD_FRAMESIZE_RAW;
ra.nframes--;
lba++;
ra.buf += CD_FRAMESIZE_RAW * nr;
ra.nframes -= nr;
lba += nr;
}
kfree(cgc.buffer);
return ret;
......
......@@ -60,6 +60,9 @@
*
* Reduced memory usage for older ARM systems
* -- Russell King <rmk@arm.linux.org.uk>
*
* Move do_SAK() into process context. Less stack use in devfs functions.
* alloc_tty_struct() always uses kmalloc() -- Andrew Morton <andrewm@uow.edu.eu> 17Mar01
*/
#include <linux/config.h>
......@@ -159,26 +162,19 @@ extern void sci_console_init(void);
#define MAX(a,b) ((a) < (b) ? (b) : (a))
#endif
static inline struct tty_struct *alloc_tty_struct(void)
static struct tty_struct *alloc_tty_struct(void)
{
struct tty_struct *tty;
if (PAGE_SIZE > 8192) {
tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
if (tty)
memset(tty, 0, sizeof(struct tty_struct));
} else
tty = (struct tty_struct *)get_zeroed_page(GFP_KERNEL);
tty = kmalloc(sizeof(struct tty_struct), GFP_KERNEL);
if (tty)
memset(tty, 0, sizeof(struct tty_struct));
return tty;
}
static inline void free_tty_struct(struct tty_struct *tty)
{
if (PAGE_SIZE > 8192)
kfree(tty);
else
free_page((unsigned long) tty);
kfree(tty);
}
/*
......@@ -1814,12 +1810,16 @@ int tty_ioctl(struct inode * inode, struct file * file,
* Now, if it would be correct ;-/ The current code has a nasty hole -
* it doesn't catch files in flight. We may send the descriptor to ourselves
* via AF_UNIX socket, close it and later fetch from socket. FIXME.
*
* Nasty bug: do_SAK is being called in interrupt context. This can
* deadlock. We punt it up to process context. AKPM - 16Mar2001
*/
void do_SAK( struct tty_struct *tty)
static void __do_SAK(void *arg)
{
#ifdef TTY_SOFT_SAK
tty_hangup(tty);
#else
struct tty_struct *tty = arg;
struct task_struct *p;
int session;
int i;
......@@ -1842,7 +1842,6 @@ void do_SAK( struct tty_struct *tty)
task_lock(p);
if (p->files) {
read_lock(&p->files->file_lock);
/* FIXME: p->files could change */
for (i=0; i < p->files->max_fds; i++) {
filp = fcheck_files(p->files, i);
if (filp && (filp->f_op == &tty_fops) &&
......@@ -1859,6 +1858,19 @@ void do_SAK( struct tty_struct *tty)
#endif
}
/*
* The tq handling here is a little racy - tty->SAK_tq may already be queued.
* But there's no mechanism to fix that without futzing with tqueue_lock.
* Fortunately we don't need to worry, because if ->SAK_tq is already queued,
* the values which we write to it will be identical to the values which it
* already has. --akpm
*/
void do_SAK(struct tty_struct *tty)
{
PREPARE_TQUEUE(&tty->SAK_tq, __do_SAK, tty);
schedule_task(&tty->SAK_tq);
}
/*
* This routine is called out of the software interrupt to flush data
* from the flip buffer to the line discipline.
......@@ -1973,6 +1985,7 @@ static void initialize_tty_struct(struct tty_struct *tty)
sema_init(&tty->atomic_write, 1);
spin_lock_init(&tty->read_lock);
INIT_LIST_HEAD(&tty->tty_files);
INIT_TQUEUE(&tty->SAK_tq, 0, 0);
}
/*
......@@ -1986,17 +1999,15 @@ void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
/*
* Register a tty device described by <driver>, with minor number <minor>.
*/
void tty_register_devfs (struct tty_driver *driver, unsigned int flags,
unsigned int minor)
void tty_register_devfs (struct tty_driver *driver, unsigned int flags, unsigned minor)
{
#ifdef CONFIG_DEVFS_FS
umode_t mode = S_IFCHR | S_IRUSR | S_IWUSR;
struct tty_struct tty;
kdev_t device = MKDEV (driver->major, minor);
int idx = minor - driver->minor_start;
char buf[32];
tty.driver = *driver;
tty.device = MKDEV (driver->major, minor);
switch (tty.device) {
switch (device) {
case TTY_DEV:
case PTMX_DEV:
mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
......@@ -2017,7 +2028,8 @@ void tty_register_devfs (struct tty_driver *driver, unsigned int flags,
(driver->major < UNIX98_PTY_SLAVE_MAJOR + UNIX98_NR_MAJORS) )
flags |= DEVFS_FL_CURRENT_OWNER;
# endif
devfs_register (NULL, tty_name (&tty, buf), flags | DEVFS_FL_DEFAULT,
sprintf(buf, driver->name, idx + driver->name_base);
devfs_register (NULL, buf, flags | DEVFS_FL_DEFAULT,
driver->major, minor, mode, &tty_fops, NULL);
#endif /* CONFIG_DEVFS_FS */
}
......@@ -2026,14 +2038,11 @@ void tty_unregister_devfs (struct tty_driver *driver, unsigned minor)
{
#ifdef CONFIG_DEVFS_FS
void * handle;
struct tty_struct tty;
int idx = minor - driver->minor_start;
char buf[32];
tty.driver = *driver;
tty.device = MKDEV(driver->major, minor);
handle = devfs_find_handle (NULL, tty_name (&tty, buf),
driver->major, minor,
sprintf(buf, driver->name, idx + driver->name_base);
handle = devfs_find_handle (NULL, buf, driver->major, minor,
DEVFS_SPECIAL_CHR, 0);
devfs_unregister (handle);
#endif /* CONFIG_DEVFS_FS */
......@@ -2218,9 +2227,6 @@ static struct tty_driver dev_console_driver;
*/
void __init tty_init(void)
{
if (sizeof(struct tty_struct) > PAGE_SIZE)
panic("size of tty structure > PAGE_SIZE!");
/*
* dev_tty_driver and dev_console_driver are actually magic
* devices which get redirected at open time. Nevertheless,
......
......@@ -26,6 +26,7 @@ if [ "$CONFIG_NET_PCMCIA" = "y" ]; then
bool ' Pcmcia Wireless LAN' CONFIG_NET_PCMCIA_RADIO
if [ "$CONFIG_NET_PCMCIA_RADIO" = "y" ]; then
dep_tristate ' Aviator/Raytheon 2.4MHz wireless support' CONFIG_PCMCIA_RAYCS $CONFIG_PCMCIA
dep_tristate ' Hermes (AT&T/Lucent/Orinoco/3com) wireless support' CONFIG_PCMCIA_HERMES $CONFIG_PCMCIA
dep_tristate ' Xircom Netwave AirSurfer wireless support' CONFIG_PCMCIA_NETWAVE $CONFIG_PCMCIA
dep_tristate ' AT&T/Lucent Wavelan wireless support' CONFIG_PCMCIA_WAVELAN $CONFIG_PCMCIA
dep_tristate ' Aironet 4500/4800 PCMCIA support' CONFIG_AIRONET4500_CS $CONFIG_AIRONET4500 $CONFIG_PCMCIA
......
......@@ -25,6 +25,7 @@ obj-$(CONFIG_PCMCIA_XIRC2PS) += xirc2ps_cs.o
obj-$(CONFIG_ARCNET_COM20020_CS)+= com20020_cs.o
# 16-bit wireless client drivers
obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o hermes.o
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
obj-$(CONFIG_PCMCIA_NETWAVE) += netwave_cs.o
obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan_cs.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -838,7 +838,7 @@ static int proc_submiturb(struct dev_state *ps, void *arg)
}
if (totlen > 32768) {
kfree(isopkt);
return -ENOMEM;
return -EINVAL;
}
uurb.buffer_length = totlen;
break;
......
......@@ -291,6 +291,7 @@ static void *hub_probe(struct usb_device *dev, unsigned int i,
INIT_LIST_HEAD(&hub->event_list);
hub->dev = dev;
init_MUTEX(&hub->khubd_sem);
/* Record the new hub's existence */
spin_lock_irqsave(&hub_event_lock, flags);
......@@ -334,6 +335,9 @@ static void hub_disconnect(struct usb_device *dev, void *ptr)
spin_unlock_irqrestore(&hub_event_lock, flags);
down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
up(&hub->khubd_sem);
if (hub->urb) {
usb_unlink_urb(hub->urb);
usb_free_urb(hub->urb);
......@@ -545,6 +549,13 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port,
return;
}
/* Some low speed devices have problems with the quick delay, so */
/* be a bit pessimistic with those devices. RHbug #23670 */
if (portstatus & USB_PORT_STAT_LOW_SPEED) {
wait_ms(400);
delay = HUB_LONG_RESET_TIME;
}
down(&usb_address0_sem);
tempstr = kmalloc(1024, GFP_KERNEL);
......@@ -639,7 +650,7 @@ static void usb_hub_events(void)
spin_lock_irqsave(&hub_event_lock, flags);
if (list_empty(&hub_event_list))
goto he_unlock;
break;
/* Grab the next entry from the beginning of the list */
tmp = hub_event_list.next;
......@@ -650,6 +661,7 @@ static void usb_hub_events(void)
list_del(tmp);
INIT_LIST_HEAD(tmp);
down(&hub->khubd_sem); /* never blocks, we were on list */
spin_unlock_irqrestore(&hub_event_lock, flags);
if (hub->error) {
......@@ -658,6 +670,7 @@ static void usb_hub_events(void)
if (usb_hub_reset(hub)) {
err("error resetting hub %d - disconnecting", dev->devnum);
usb_hub_disconnect(dev);
up(&hub->khubd_sem);
continue;
}
......@@ -733,9 +746,9 @@ static void usb_hub_events(void)
usb_hub_power_on(hub);
}
}
up(&hub->khubd_sem);
} /* end while (1) */
he_unlock:
spin_unlock_irqrestore(&hub_event_lock, flags);
}
......
......@@ -108,6 +108,8 @@ struct usb_hub {
int nports;
struct usb_hub_descriptor *descriptor;
struct semaphore khubd_sem;
};
#endif
This diff is collapsed.
This diff is collapsed.
......@@ -264,8 +264,8 @@ static void belkin_sa_shutdown (struct usb_serial *serial)
belkin_sa_close (&serial->port[i], NULL);
}
/* My special items, the standard routines free my urbs */
if (serial->port->private)
kfree(serial->port->private);
if (serial->port[i].private)
kfree(serial->port[i].private);
}
}
......
......@@ -346,8 +346,8 @@ static void mct_u232_shutdown (struct usb_serial *serial)
mct_u232_close (&serial->port[i], NULL);
}
/* My special items, the standard routines free my urbs */
if (serial->port->private)
kfree(serial->port->private);
if (serial->port[i].private)
kfree(serial->port[i].private);
}
} /* mct_u232_shutdown */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment