patch-2.1.37 linux/fs/locks.c

Next file: linux/fs/msdos/msdosfs_syms.c
Previous file: linux/fs/lockd/svcsubs.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.36/linux/fs/locks.c linux/fs/locks.c
@@ -100,6 +100,9 @@
  *
  *  Some adaptations for NFS support.
  *  Olaf Kirch (okir@monad.swb.de), Dec 1996,
+ *
+ *  Fixed /proc/locks interface so that we can't overrun the buffer we are handed.
+ *  Andy Walker (andy@lysaker.kvaerner.no), May 12, 1997.
  */
 
 #include <linux/malloc.h>
@@ -132,7 +135,7 @@
 static struct file_lock *locks_alloc_lock(struct file_lock *fl);
 static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl);
 static void locks_delete_lock(struct file_lock **thisfl_p, unsigned int wait);
-static char *lock_get_status(struct file_lock *fl, char *p, int id, char *pfx);
+static char *lock_get_status(struct file_lock *fl, int id, char *pfx);
 
 static void locks_insert_block(struct file_lock *blocker, struct file_lock *waiter);
 static void locks_delete_block(struct file_lock *blocker, struct file_lock *waiter);
@@ -227,6 +230,7 @@
 posix_block_lock(struct file_lock *blocker, struct file_lock *waiter)
 {
 	locks_insert_block(blocker, waiter);
+	return;
 }
 
 void
@@ -234,6 +238,7 @@
 {
 	if (waiter->fl_prevblock)
 		locks_delete_block(waiter->fl_prevblock, waiter);
+	return;
 }
 
 /* Wake up processes blocked waiting for blocker.
@@ -269,20 +274,20 @@
 {
 	struct file_lock file_lock;
 	struct file *filp;
-	int err;
+	int error;
 
 	lock_kernel();
 	if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd]))
-		err = -EBADF;
+		error = -EBADF;
 	else if (!flock_make_lock(filp, &file_lock, cmd))
-		err = -EINVAL;
+		error = -EINVAL;
 	else if ((file_lock.fl_type != F_UNLCK) && !(filp->f_mode & 3))
-		err = -EBADF;
+		error = -EBADF;
 	else
-		err = flock_lock_file(filp, &file_lock,
-				      (cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1);
+		error = flock_lock_file(filp, &file_lock,
+					(cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1);
 	unlock_kernel();
-	return err;
+	return (error);
 }
 
 /* Report the first existing lock that would conflict with l.
@@ -298,7 +303,7 @@
 	if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd]))
 		return (-EBADF);
 	if (copy_from_user(&flock, l, sizeof(flock)))
-		return -EFAULT; 	
+		return (-EFAULT);
 
 	if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK))
 		return (-EINVAL);
@@ -308,9 +313,9 @@
 
 	if (filp->f_op->lock) {
 		error = filp->f_op->lock(filp->f_inode, filp,
-					F_GETLK, &file_lock);
+					 F_GETLK, &file_lock);
 		if (error < 0)
-			return error;
+			return (error);
 		fl = &file_lock;
 	} else {
 		fl = posix_test_lock(filp, &file_lock);
@@ -323,12 +328,12 @@
 			fl->fl_end - fl->fl_start + 1;
 		flock.l_whence = 0;
 		flock.l_type = fl->fl_type;
-		return copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0; 
+		return (copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0);
 	} else {
 		flock.l_type = F_UNLCK;
   	}
   
-	return copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0; 
+	return (copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0);
 }
 
 /* Apply the lock described by l to an open file descriptor.
@@ -366,7 +371,7 @@
 	}
 
 	if (copy_from_user(&flock, l, sizeof(flock)))
-		return -EFAULT; 	
+		return (-EFAULT);
 	if (!posix_make_lock(filp, &file_lock, &flock))
 		return (-EINVAL);
 	
@@ -399,13 +404,13 @@
 		break;
 #endif
 	default:
-		return -EINVAL;
+		return (-EINVAL);
 	}
 
 	if (filp->f_op->lock != NULL) {
 		error = filp->f_op->lock(filp->f_inode, filp, cmd, &file_lock);
 		if (error < 0)
-			return error;
+			return (error);
 	}
 
 	return (posix_lock_file(filp, &file_lock, cmd == F_SETLKW));
@@ -457,7 +462,7 @@
 			break;
 	}
 
-	return cfl;
+	return (cfl);
 }
 
 int locks_verify_locked(struct inode *inode)
@@ -1044,16 +1049,18 @@
 }
 
 
-static char *lock_get_status(struct file_lock *fl, char *p, int id, char *pfx)
+static char *lock_get_status(struct file_lock *fl, int id, char *pfx)
 {
+	static char temp[129];
+	char *p = temp;
 	struct inode *inode;
 
 	inode = fl->fl_file->f_inode;
 
 	p += sprintf(p, "%d:%s ", id, pfx);
 	if (fl->fl_flags & FL_POSIX) {
-		p += sprintf(p, "%s %s ",
-			     (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX",
+		p += sprintf(p, "%6s %s ",
+			     (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ",
 			     (IS_MANDLOCK(inode) &&
 			      (inode->i_mode & (S_IXGRP | S_ISGID)) == S_ISGID) ?
 			     "MANDATORY" : "ADVISORY ");
@@ -1066,28 +1073,68 @@
 		     fl->fl_pid,
 		     kdevname(inode->i_dev), inode->i_ino, fl->fl_start,
 		     fl->fl_end);
-	p += sprintf(p, "%08lx %08lx %08lx %08lx %08lx\n",
-		     (long)fl, (long)fl->fl_prevlink, (long)fl->fl_nextlink,
-		     (long)fl->fl_next, (long)fl->fl_nextblock);
-	return (p);
+	sprintf(p, "%08lx %08lx %08lx %08lx %08lx\n",
+		(long)fl, (long)fl->fl_prevlink, (long)fl->fl_nextlink,
+		(long)fl->fl_next, (long)fl->fl_nextblock);
+	return (temp);
 }
 
-int get_locks_status(char *buf)
+static inline int copy_lock_status(char *p, char **q, off_t pos, int len,
+				   off_t offset, int length)
+{
+	int i;
+
+	i = pos - offset;
+	if (i > 0) {
+		if (i >= length) {
+			i = len + length - i;
+			memcpy(*q, p, i);
+			*q += i;
+			return (0);
+		}
+		if (i < len) {
+			p += len - i;
+		}
+		else
+			i = len;
+		memcpy(*q, p, i);
+		*q += i;
+	}
+	
+	return (1);
+}
+
+int get_locks_status(char *buffer, char **start, off_t offset, int length)
 {
 	struct file_lock *fl;
 	struct file_lock *bfl;
 	char *p;
+	char *q = buffer;
 	int i;
+	int len;
+	off_t pos = 0;
 
-	p = buf;
 	for (fl = file_lock_table, i = 1; fl != NULL; fl = fl->fl_nextlink, i++) {
-		p = lock_get_status(fl, p, i, "");
+		p = lock_get_status(fl, i, "");
+		len = strlen(p);
+		pos += len;
+		if (!copy_lock_status(p, &q, pos, len, offset, length))
+			goto done;
 		if ((bfl = fl->fl_nextblock) == NULL)
 			continue;
 		do {
-			p = lock_get_status(bfl, p, i, " ->");
+			p = lock_get_status(bfl, i, " ->");
+			len = strlen(p);
+			pos += len;
+			if (!copy_lock_status(p, &q, pos, len, offset, length))
+				goto done;
 		} while ((bfl = bfl->fl_nextblock) != fl);
 	}
-	return (p - buf);
+done:
+	if (q != buffer)
+		*start = buffer;
+	return (q - buffer);
 }
+
+
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov