splat: Fix log buffer locking
The Fedora 3.6 debug kernel identified the following issue where we call copy_to_user() under a spin lock(). This used to be safe in older kernels but no longer appears to be true so the spin lock was changed to a mutex. None of this code is performance critical so allowing the process to sleep is harmless. Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
parent
df870a697f
commit
0e149d4204
|
@ -71,7 +71,7 @@ splat_open(struct inode *inode, struct file *file)
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
spin_lock_init(&info->info_lock);
|
mutex_init(&info->info_lock);
|
||||||
info->info_size = SPLAT_INFO_BUFFER_SIZE;
|
info->info_size = SPLAT_INFO_BUFFER_SIZE;
|
||||||
info->info_buffer = (char *)vmalloc(SPLAT_INFO_BUFFER_SIZE);
|
info->info_buffer = (char *)vmalloc(SPLAT_INFO_BUFFER_SIZE);
|
||||||
if (info->info_buffer == NULL) {
|
if (info->info_buffer == NULL) {
|
||||||
|
@ -100,6 +100,7 @@ splat_release(struct inode *inode, struct file *file)
|
||||||
ASSERT(info);
|
ASSERT(info);
|
||||||
ASSERT(info->info_buffer);
|
ASSERT(info->info_buffer);
|
||||||
|
|
||||||
|
mutex_destroy(&info->info_lock);
|
||||||
vfree(info->info_buffer);
|
vfree(info->info_buffer);
|
||||||
kfree(info);
|
kfree(info);
|
||||||
|
|
||||||
|
@ -114,10 +115,10 @@ splat_buffer_clear(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
|
||||||
ASSERT(info);
|
ASSERT(info);
|
||||||
ASSERT(info->info_buffer);
|
ASSERT(info->info_buffer);
|
||||||
|
|
||||||
spin_lock(&info->info_lock);
|
mutex_lock(&info->info_lock);
|
||||||
memset(info->info_buffer, 0, info->info_size);
|
memset(info->info_buffer, 0, info->info_size);
|
||||||
info->info_head = info->info_buffer;
|
info->info_head = info->info_buffer;
|
||||||
spin_unlock(&info->info_lock);
|
mutex_unlock(&info->info_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +133,7 @@ splat_buffer_size(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
|
||||||
ASSERT(info);
|
ASSERT(info);
|
||||||
ASSERT(info->info_buffer);
|
ASSERT(info->info_buffer);
|
||||||
|
|
||||||
spin_lock(&info->info_lock);
|
mutex_lock(&info->info_lock);
|
||||||
if (kcfg->cfg_arg1 > 0) {
|
if (kcfg->cfg_arg1 > 0) {
|
||||||
|
|
||||||
size = kcfg->cfg_arg1;
|
size = kcfg->cfg_arg1;
|
||||||
|
@ -157,7 +158,7 @@ splat_buffer_size(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
|
||||||
if (copy_to_user((struct splat_cfg_t __user *)arg, kcfg, sizeof(*kcfg)))
|
if (copy_to_user((struct splat_cfg_t __user *)arg, kcfg, sizeof(*kcfg)))
|
||||||
rc = -EFAULT;
|
rc = -EFAULT;
|
||||||
out:
|
out:
|
||||||
spin_unlock(&info->info_lock);
|
mutex_unlock(&info->info_lock);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -508,7 +509,7 @@ static ssize_t splat_write(struct file *file, const char __user *buf,
|
||||||
ASSERT(info);
|
ASSERT(info);
|
||||||
ASSERT(info->info_buffer);
|
ASSERT(info->info_buffer);
|
||||||
|
|
||||||
spin_lock(&info->info_lock);
|
mutex_lock(&info->info_lock);
|
||||||
|
|
||||||
/* Write beyond EOF */
|
/* Write beyond EOF */
|
||||||
if (*ppos >= info->info_size) {
|
if (*ppos >= info->info_size) {
|
||||||
|
@ -528,7 +529,7 @@ static ssize_t splat_write(struct file *file, const char __user *buf,
|
||||||
*ppos += count;
|
*ppos += count;
|
||||||
rc = count;
|
rc = count;
|
||||||
out:
|
out:
|
||||||
spin_unlock(&info->info_lock);
|
mutex_unlock(&info->info_lock);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,7 +546,7 @@ static ssize_t splat_read(struct file *file, char __user *buf,
|
||||||
ASSERT(info);
|
ASSERT(info);
|
||||||
ASSERT(info->info_buffer);
|
ASSERT(info->info_buffer);
|
||||||
|
|
||||||
spin_lock(&info->info_lock);
|
mutex_lock(&info->info_lock);
|
||||||
|
|
||||||
/* Read beyond EOF */
|
/* Read beyond EOF */
|
||||||
if (*ppos >= info->info_size)
|
if (*ppos >= info->info_size)
|
||||||
|
@ -563,7 +564,7 @@ static ssize_t splat_read(struct file *file, char __user *buf,
|
||||||
*ppos += count;
|
*ppos += count;
|
||||||
rc = count;
|
rc = count;
|
||||||
out:
|
out:
|
||||||
spin_unlock(&info->info_lock);
|
mutex_unlock(&info->info_lock);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,7 +580,7 @@ static loff_t splat_seek(struct file *file, loff_t offset, int origin)
|
||||||
ASSERT(info);
|
ASSERT(info);
|
||||||
ASSERT(info->info_buffer);
|
ASSERT(info->info_buffer);
|
||||||
|
|
||||||
spin_lock(&info->info_lock);
|
mutex_lock(&info->info_lock);
|
||||||
|
|
||||||
switch (origin) {
|
switch (origin) {
|
||||||
case 0: /* SEEK_SET - No-op just do it */
|
case 0: /* SEEK_SET - No-op just do it */
|
||||||
|
@ -598,7 +599,7 @@ static loff_t splat_seek(struct file *file, loff_t offset, int origin)
|
||||||
rc = offset;
|
rc = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock(&info->info_lock);
|
mutex_unlock(&info->info_lock);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ typedef struct splat_subsystem {
|
||||||
#define SPLAT_INFO_BUFFER_REDZONE 256
|
#define SPLAT_INFO_BUFFER_REDZONE 256
|
||||||
|
|
||||||
typedef struct splat_info {
|
typedef struct splat_info {
|
||||||
spinlock_t info_lock;
|
struct mutex info_lock;
|
||||||
int info_size;
|
int info_size;
|
||||||
char *info_buffer;
|
char *info_buffer;
|
||||||
char *info_head; /* Internal kernel use only */
|
char *info_head; /* Internal kernel use only */
|
||||||
|
@ -136,7 +136,7 @@ typedef struct splat_info {
|
||||||
ASSERT(_info_); \
|
ASSERT(_info_); \
|
||||||
ASSERT(_info_->info_buffer); \
|
ASSERT(_info_->info_buffer); \
|
||||||
\
|
\
|
||||||
spin_lock(&_info_->info_lock); \
|
mutex_lock(&_info_->info_lock); \
|
||||||
\
|
\
|
||||||
/* Don't allow the kernel to start a write in the red zone */ \
|
/* Don't allow the kernel to start a write in the red zone */ \
|
||||||
if ((int)(_info_->info_head - _info_->info_buffer) > \
|
if ((int)(_info_->info_head - _info_->info_buffer) > \
|
||||||
|
@ -148,7 +148,7 @@ typedef struct splat_info {
|
||||||
_info_->info_head += _rc_; \
|
_info_->info_head += _rc_; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
spin_unlock(&_info_->info_lock); \
|
mutex_unlock(&_info_->info_lock); \
|
||||||
_rc_; \
|
_rc_; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue