[Mplayer-cvslog] CVS: main/libmpdvdkit2 ioctl.c,1.2,1.3
Jürgen Keil CVS
jkeil at mplayerhq.hu
Fri Dec 27 17:29:14 CET 2002
Update of /cvsroot/mplayer/main/libmpdvdkit2
In directory mail:/var/tmp.root/cvs-serv13257
Modified Files:
ioctl.c
Log Message:
Fix DVD authentication on Solaris 9.
Solaris 9 does not allow USCSICMD ioctls for non-root users on vold devices
any more; they are failing with an EPERM "permission denied" error. Now, only
root is allowed to run USCSICMD ioctls on vold devices.
Fortunatelly there's a new subroutine exported from libsmedia.so
(smedia_uscsi_cmd) which allows non-root users to perform user mode SCSI
commands on a vold device. (This works with a help of a daemon running as
user root, /usr/lib/smedia/rpc.smserverd)
This change detects the presence of function "smedia_uscsi_cmd" in library
libsmedia.so at runtime, and uses this function if it's found (i.e. on
solaris 9 smedia_uscsi_cmd() is used to execture user mode scsi commands).
On solaris 8 or older, "smedia_uscsi_cmd" is not available and the code
falls back to the old ioctl(.. USCSICMD ..) method.
Index: ioctl.c
===================================================================
RCS file: /cvsroot/mplayer/main/libmpdvdkit2/ioctl.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- ioctl.c 11 Nov 2002 00:53:46 -0000 1.2
+++ ioctl.c 27 Dec 2002 16:29:11 -0000 1.3
@@ -76,10 +76,12 @@
# include <sys/scsi.h>
#endif
#ifdef SOLARIS_USCSI
+# include <dlfcn.h>
# include <unistd.h>
# include <stropts.h>
# include <sys/scsi/scsi_types.h>
# include <sys/scsi/impl/uscsi.h>
+# include <sys/smedia.h>
#endif
#ifdef DARWIN_DVD_IOCTL
# include <IOKit/storage/IODVDMediaBSDClient.h>
@@ -112,6 +114,7 @@
*****************************************************************************/
#if defined( SOLARIS_USCSI )
static void SolarisInitUSCSI( struct uscsi_cmd *p_sc, int i_type );
+static int SolarisSendUSCSI( int fd, struct uscsi_cmd *p_sc );
#endif
/*****************************************************************************
@@ -191,7 +194,7 @@
rs_cdb.cdb_opaque[ 6 ] = i_layer;
rs_cdb.cdb_opaque[ 7 ] = DVD_STRUCT_COPYRIGHT;
- i_ret = ioctl(i_fd, USCSICMD, &sc);
+ i_ret = SolarisSendUSCSI(i_fd, &sc);
if( i_ret < 0 || sc.uscsi_status ) {
i_ret = -1;
@@ -363,7 +366,7 @@
rs_cdb.cdb_opaque[ 7 ] = DVD_STRUCT_DISCKEY;
rs_cdb.cdb_opaque[ 10 ] = *pi_agid << 6;
- i_ret = ioctl( i_fd, USCSICMD, &sc );
+ i_ret = SolarisSendUSCSI( i_fd, &sc );
if( i_ret < 0 || sc.uscsi_status )
{
@@ -525,7 +528,7 @@
rs_cdb.cdb_opaque[ 5 ] = ( i_pos ) & 0xff;
rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_TITLE_KEY | (*pi_agid << 6);
- i_ret = ioctl( i_fd, USCSICMD, &sc );
+ i_ret = SolarisSendUSCSI( i_fd, &sc );
if( i_ret < 0 || sc.uscsi_status )
{
@@ -676,7 +679,7 @@
rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
- i_ret = ioctl( i_fd, USCSICMD, &sc );
+ i_ret = SolarisSendUSCSI( i_fd, &sc );
if( i_ret < 0 || sc.uscsi_status )
{
@@ -798,7 +801,7 @@
rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
- i_ret = ioctl( i_fd, USCSICMD, &sc );
+ i_ret = SolarisSendUSCSI( i_fd, &sc );
if( i_ret < 0 || sc.uscsi_status )
{
@@ -932,7 +935,7 @@
rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_ASF;
- i_ret = ioctl( i_fd, USCSICMD, &sc );
+ i_ret = SolarisSendUSCSI( i_fd, &sc );
if( i_ret < 0 || sc.uscsi_status )
{
@@ -1065,7 +1068,7 @@
rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
- i_ret = ioctl( i_fd, USCSICMD, &sc );
+ i_ret = SolarisSendUSCSI( i_fd, &sc );
if( i_ret < 0 || sc.uscsi_status )
{
@@ -1186,7 +1189,7 @@
rs_cdb.cdb_opaque[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
- i_ret = ioctl( i_fd, USCSICMD, &sc );
+ i_ret = SolarisSendUSCSI( i_fd, &sc );
if( i_ret < 0 || sc.uscsi_status )
{
@@ -1310,7 +1313,7 @@
p_buffer[ 1 ] = 0xe;
memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE );
- if( ioctl( i_fd, USCSICMD, &sc ) < 0 || sc.uscsi_status )
+ if( SolarisSendUSCSI( i_fd, &sc ) < 0 || sc.uscsi_status )
{
return -1;
}
@@ -1447,7 +1450,7 @@
p_buffer[ 1 ] = 0xa;
memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE );
- if( ioctl( i_fd, USCSICMD, &sc ) < 0 || sc.uscsi_status )
+ if( SolarisSendUSCSI( i_fd, &sc ) < 0 || sc.uscsi_status )
{
return -1;
}
@@ -1589,7 +1592,7 @@
rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_RPC;
- i_ret = ioctl( i_fd, USCSICMD, &sc );
+ i_ret = SolarisSendUSCSI( i_fd, &sc );
if( i_ret < 0 || sc.uscsi_status )
{
@@ -1786,6 +1789,54 @@
p_sc->uscsi_cdblen = 12;
USCSI_TIMEOUT( p_sc, 15 );
+}
+
+/*****************************************************************************
+ * SolarisSendUSCSI: send a USCSICMD structure to the Solaris kernel
+ * for execution
+ *****************************************************************************
+ * When available, this function uses the function smedia_uscsi_cmd()
+ * from solaris' libsmedia library (solaris 9 or newer) to execute the
+ * USCSI command. smedia_uscsi_cmd() allows USCSI commands for
+ * non-root users on removable media devices on solaris 9; sending the
+ * USCSI command directly to the device using the USCSICMD ioctl fails
+ * with an EPERM error on solaris 9.
+ *
+ * The code will fall back to the USCSICMD ioctl method, when
+ * libsmedia.so is not available or does not export the
+ * smedia_uscsi_cmd() function (on solaris releases upto and including
+ * solaris 8). Fortunatelly, on these old releases non-root users are
+ * allowed to perform USCSICMD ioctls on removable media devices.
+ *****************************************************************************/
+static int SolarisSendUSCSI( int i_fd, struct uscsi_cmd *p_sc ) {
+ void *sm_hdl;
+ static int initialized;
+ static void* (*sm_get_handle)(int32_t);
+ static int (*sm_release_handle)(void*);
+ static int (*sm_uscsi_cmd)(void*, struct uscsi_cmd *);
+
+ if (!initialized)
+ {
+ void *smedia_lib;
+
+ smedia_lib = dlopen("libsmedia.so", RTLD_NOW);
+ if (smedia_lib) {
+ sm_get_handle = dlsym(smedia_lib, "smedia_get_handle");
+ sm_release_handle = dlsym(smedia_lib, "smedia_release_handle");
+ sm_uscsi_cmd = dlsym(smedia_lib, "smedia_uscsi_cmd");
+ }
+ initialized = 1;
+ }
+
+ if (sm_get_handle && sm_uscsi_cmd && sm_release_handle
+ && (sm_hdl = sm_get_handle(i_fd)))
+ {
+ int i_ret = sm_uscsi_cmd(sm_hdl, p_sc);
+ sm_release_handle(sm_hdl);
+ return i_ret;
+ }
+
+ return ioctl( i_fd, USCSICMD, p_sc );
}
#endif
More information about the MPlayer-cvslog
mailing list