IB/ipath: Prevent random program use of diags interface

To prevent random utility reads and writes of the diag interface to the
chip, we first require a handshake of reading from offset 0 and writing
to offset 0 before any other reads or writes can be done through the
diags device.   Otherwise chip errors can be triggered.

Signed-off-by: Dave Olson <dave.olson@qlogic.com>
Signed-off-by: Bryan O'Sullivan <bryan.osullivan@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
Bryan O'Sullivan 2007-03-15 14:45:10 -07:00 committed by Roland Dreier
parent f5408ac7cc
commit 490462c268

View File

@ -296,7 +296,7 @@ static int ipath_diag_open(struct inode *in, struct file *fp)
} }
fp->private_data = dd; fp->private_data = dd;
ipath_diag_inuse = 1; ipath_diag_inuse = -2;
diag_set_link = 0; diag_set_link = 0;
ret = 0; ret = 0;
@ -461,6 +461,8 @@ static ssize_t ipath_diag_read(struct file *fp, char __user *data,
else if ((count % 4) || (*off % 4)) else if ((count % 4) || (*off % 4))
/* address or length is not 32-bit aligned, hence invalid */ /* address or length is not 32-bit aligned, hence invalid */
ret = -EINVAL; ret = -EINVAL;
else if (ipath_diag_inuse < 1 && (*off || count != 8))
ret = -EINVAL; /* prevent cat /dev/ipath_diag* */
else if ((count % 8) || (*off % 8)) else if ((count % 8) || (*off % 8))
/* address or length not 64-bit aligned; do 32-bit reads */ /* address or length not 64-bit aligned; do 32-bit reads */
ret = ipath_read_umem32(dd, data, kreg_base + *off, count); ret = ipath_read_umem32(dd, data, kreg_base + *off, count);
@ -470,6 +472,8 @@ static ssize_t ipath_diag_read(struct file *fp, char __user *data,
if (ret >= 0) { if (ret >= 0) {
*off += count; *off += count;
ret = count; ret = count;
if (ipath_diag_inuse == -2)
ipath_diag_inuse++;
} }
return ret; return ret;
@ -489,6 +493,9 @@ static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
else if ((count % 4) || (*off % 4)) else if ((count % 4) || (*off % 4))
/* address or length is not 32-bit aligned, hence invalid */ /* address or length is not 32-bit aligned, hence invalid */
ret = -EINVAL; ret = -EINVAL;
else if ((ipath_diag_inuse == -1 && (*off || count != 8)) ||
ipath_diag_inuse == -2) /* read qw off 0, write qw off 0 */
ret = -EINVAL; /* before any other write allowed */
else if ((count % 8) || (*off % 8)) else if ((count % 8) || (*off % 8))
/* address or length not 64-bit aligned; do 32-bit writes */ /* address or length not 64-bit aligned; do 32-bit writes */
ret = ipath_write_umem32(dd, kreg_base + *off, data, count); ret = ipath_write_umem32(dd, kreg_base + *off, data, count);
@ -498,6 +505,8 @@ static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
if (ret >= 0) { if (ret >= 0) {
*off += count; *off += count;
ret = count; ret = count;
if (ipath_diag_inuse == -1)
ipath_diag_inuse = 1; /* all read/write OK now */
} }
return ret; return ret;