Пример #1
0
/* Check that the current application belongs to the
 * requested GID */
static bool SCXLNXConnCheckGID(gid_t nRequestedGID)
{
    if (nRequestedGID == current_egid()) {
        return true;
    } else {
        u32    nSize;
        u32    i;
        /* Look in the supplementary GIDs */
        get_group_info(GROUP_INFO);
        nSize = GROUP_INFO->ngroups;
        for (i = 0; i < nSize; i++)
            if (nRequestedGID == GROUP_AT(GROUP_INFO , i))
                return true;
    }
    return false;
}
Пример #2
0
/* Check that the current application belongs to the
 * requested GID */
static bool tf_check_gid(gid_t requested_gid)
{
	if (requested_gid == current_egid()) {
		return true;
	} else {
		u32    size;
		u32    i;
		/* Look in the supplementary GIDs */
		get_group_info(GROUP_INFO);
		size = GROUP_INFO->ngroups;
		for (i = 0; i < size; i++)
			if (requested_gid == GROUP_AT(GROUP_INFO , i))
				return true;
	}
	return false;
}
Пример #3
0
static long dek_ioctl_kek(struct file *file,
		unsigned int cmd, unsigned long arg)
{
	unsigned int minor;
	if(!is_container_app() && !is_root()) {
		DEK_LOGE("Current process can't access kek device\n");
		DEK_LOGE("Current process info :: "
				"uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u "
				"fsuid=%u fsgid=%u\n",
				current_uid(), current_gid(), current_euid(),
				current_egid(), current_suid(), current_sgid(),
				current_fsuid(), current_fsgid());
		dek_add_to_log(000, "Access denied to kek device");
		return -EACCES;
	}

	minor = iminor(file->f_path.dentry->d_inode);
	return dek_do_ioctl_kek(minor, cmd, arg);
}
Пример #4
0
/**
 * tomoyo_print_header - Get header line of audit log.
 *
 * @r: Pointer to "struct tomoyo_request_info".
 *
 * Returns string representation.
 *
 * This function uses kmalloc(), so caller must kfree() if this function
 * didn't return NULL.
 */
static char *tomoyo_print_header(struct tomoyo_request_info *r)
{
	struct tomoyo_time stamp;
	const pid_t gpid = task_pid_nr(current);
	struct tomoyo_obj_info *obj = r->obj;
	static const int tomoyo_buffer_len = 4096;
	char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS);
	int pos;
	u8 i;
	if (!buffer)
		return NULL;
	{
		struct timeval tv;
		do_gettimeofday(&tv);
		tomoyo_convert_time(tv.tv_sec, &stamp);
	}
	pos = snprintf(buffer, tomoyo_buffer_len - 1,
		       "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s "
		       "granted=%s (global-pid=%u) task={ pid=%u ppid=%u "
		       "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u "
		       "fsuid=%u fsgid=%u }", stamp.year, stamp.month,
		       stamp.day, stamp.hour, stamp.min, stamp.sec, r->profile,
		       tomoyo_mode[r->mode], tomoyo_yesno(r->granted), gpid,
		       tomoyo_sys_getpid(), tomoyo_sys_getppid(),
		       current_uid(), current_gid(), current_euid(),
		       current_egid(), current_suid(), current_sgid(),
		       current_fsuid(), current_fsgid());
	if (!obj)
		goto no_obj_info;
	if (!obj->validate_done) {
		tomoyo_get_attributes(obj);
		obj->validate_done = true;
	}
	for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
		struct tomoyo_mini_stat *stat;
		unsigned int dev;
		umode_t mode;
		if (!obj->stat_valid[i])
			continue;
		stat = &obj->stat[i];
		dev = stat->dev;
		mode = stat->mode;
		if (i & 1) {
			pos += snprintf(buffer + pos,
					tomoyo_buffer_len - 1 - pos,
					" path%u.parent={ uid=%u gid=%u "
					"ino=%lu perm=0%o }", (i >> 1) + 1,
					stat->uid, stat->gid, (unsigned long)
					stat->ino, stat->mode & S_IALLUGO);
			continue;
		}
		pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos,
				" path%u={ uid=%u gid=%u ino=%lu major=%u"
				" minor=%u perm=0%o type=%s", (i >> 1) + 1,
				stat->uid, stat->gid, (unsigned long)
				stat->ino, MAJOR(dev), MINOR(dev),
				mode & S_IALLUGO, tomoyo_filetype(mode));
		if (S_ISCHR(mode) || S_ISBLK(mode)) {
			dev = stat->rdev;
			pos += snprintf(buffer + pos,
					tomoyo_buffer_len - 1 - pos,
					" dev_major=%u dev_minor=%u",
					MAJOR(dev), MINOR(dev));
		}
		pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos,
				" }");
	}
Пример #5
0
/*
 * Opens a client session to the Secure World
 */
int SCXLNXConnOpenClientSession(
    struct SCXLNX_CONNECTION *pConn,
    union SCX_COMMAND_MESSAGE *pMessage,
    union SCX_ANSWER_MESSAGE *pAnswer)
{
    int nError = 0;
    struct SCXLNX_SHMEM_DESC *pShmemDesc[4] = {NULL};
    u32 i;

    dprintk(KERN_INFO "SCXLNXConnOpenClientSession(%p)\n", pConn);

    /*
     * Initialize the message size with no login data. This will be later
     * adjusted the the cases below
     */
    pMessage->sOpenClientSessionMessage.nMessageSize =
        (sizeof(struct SCX_COMMAND_OPEN_CLIENT_SESSION) - 20
         - sizeof(struct SCX_COMMAND_HEADER))/4;

    switch (pMessage->sOpenClientSessionMessage.nLoginType) {
    case SCX_LOGIN_PUBLIC:
        /* Nothing to do */
        break;

    case SCX_LOGIN_USER:
        /*
         * Send the EUID of the calling application in the login data.
         * Update message size.
         */
        *(u32 *) &pMessage->sOpenClientSessionMessage.sLoginData =
            current_euid();
#ifndef CONFIG_ANDROID
        pMessage->sOpenClientSessionMessage.nLoginType =
            (u32) SCX_LOGIN_USER_LINUX_EUID;
#else
        pMessage->sOpenClientSessionMessage.nLoginType =
            (u32) SCX_LOGIN_USER_ANDROID_EUID;
#endif

        /* Added one word */
        pMessage->sOpenClientSessionMessage.nMessageSize += 1;
        break;

    case SCX_LOGIN_GROUP: {
        /* Check requested GID */
        gid_t  nRequestedGID =
            *(u32 *) pMessage->sOpenClientSessionMessage.sLoginData;

        if (!SCXLNXConnCheckGID(nRequestedGID)) {
            dprintk(KERN_ERR "SCXLNXConnOpenClientSession(%p) "
                    "SCX_LOGIN_GROUP: requested GID (0x%x) does "
                    "not match real eGID (0x%x)"
                    "or any of the supplementary GIDs\n",
                    pConn, nRequestedGID, current_egid());
            nError = -EACCES;
            goto error;
        }
#ifndef CONFIG_ANDROID
        pMessage->sOpenClientSessionMessage.nLoginType =
            SCX_LOGIN_GROUP_LINUX_GID;
#else
        pMessage->sOpenClientSessionMessage.nLoginType =
            SCX_LOGIN_GROUP_ANDROID_GID;
#endif

        pMessage->sOpenClientSessionMessage.nMessageSize += 1; /* GID */
        break;
    }

#ifndef CONFIG_ANDROID
    case SCX_LOGIN_APPLICATION: {
        /*
         * Compute SHA-1 hash of the application fully-qualified path
         * name.  Truncate the hash to 16 bytes and send it as login
         * data.  Update message size.
         */
        u8 pSHA1Hash[SHA1_DIGEST_SIZE];

        nError = SCXLNXConnHashApplicationPathAndData(pSHA1Hash,
                 NULL, 0);
        if (nError != 0) {
            dprintk(KERN_ERR "SCXLNXConnOpenClientSession: "
                    "error in SCXLNXConnHashApplicationPath"
                    "AndData\n");
            goto error;
        }
        memcpy(&pMessage->sOpenClientSessionMessage.sLoginData,
               pSHA1Hash, 16);
        pMessage->sOpenClientSessionMessage.nLoginType =
            SCX_LOGIN_APPLICATION_LINUX_PATH_SHA1_HASH;
        /* 16 bytes */
        pMessage->sOpenClientSessionMessage.nMessageSize += 4;
        break;
    }
#else
    case SCX_LOGIN_APPLICATION:
        /*
         * Send the real UID of the calling application in the login
         * data. Update message size.
         */
        *(u32 *) &pMessage->sOpenClientSessionMessage.sLoginData =
            current_uid();

        pMessage->sOpenClientSessionMessage.nLoginType =
            (u32) SCX_LOGIN_APPLICATION_ANDROID_UID;

        /* Added one word */
        pMessage->sOpenClientSessionMessage.nMessageSize += 1;
        break;
#endif

#ifndef CONFIG_ANDROID
    case SCX_LOGIN_APPLICATION_USER: {
        /*
         * Compute SHA-1 hash of the concatenation of the application
         * fully-qualified path name and the EUID of the calling
         * application.  Truncate the hash to 16 bytes and send it as
         * login data.  Update message size.
         */
        u8 pSHA1Hash[SHA1_DIGEST_SIZE];

        nError = SCXLNXConnHashApplicationPathAndData(pSHA1Hash,
                 (u8 *) &(current_euid()), sizeof(current_euid()));
        if (nError != 0) {
            dprintk(KERN_ERR "SCXLNXConnOpenClientSession: "
                    "error in SCXLNXConnHashApplicationPath"
                    "AndData\n");
            goto error;
        }
        memcpy(&pMessage->sOpenClientSessionMessage.sLoginData,
               pSHA1Hash, 16);
        pMessage->sOpenClientSessionMessage.nLoginType =
            SCX_LOGIN_APPLICATION_USER_LINUX_PATH_EUID_SHA1_HASH;

        /* 16 bytes */
        pMessage->sOpenClientSessionMessage.nMessageSize += 4;

        break;
    }
#else
    case SCX_LOGIN_APPLICATION_USER:
        /*
         * Send the real UID and the EUID of the calling application in
         * the login data. Update message size.
         */
        *(u32 *) &pMessage->sOpenClientSessionMessage.sLoginData =
            current_uid();
        *(u32 *) &pMessage->sOpenClientSessionMessage.sLoginData[4] =
            current_euid();

        pMessage->sOpenClientSessionMessage.nLoginType =
            SCX_LOGIN_APPLICATION_USER_ANDROID_UID_EUID;

        /* Added two words */
        pMessage->sOpenClientSessionMessage.nMessageSize += 2;
        break;
#endif

#ifndef CONFIG_ANDROID
    case SCX_LOGIN_APPLICATION_GROUP: {
        /*
         * Check requested GID.  Compute SHA-1 hash of the concatenation
         * of the application fully-qualified path name and the
         * requested GID.  Update message size
         */
        gid_t  nRequestedGID;
        u8     pSHA1Hash[SHA1_DIGEST_SIZE];

        nRequestedGID =	*(u32 *) &pMessage->sOpenClientSessionMessage.
                        sLoginData;

        if (!SCXLNXConnCheckGID(nRequestedGID)) {
            dprintk(KERN_ERR "SCXLNXConnOpenClientSession(%p) "
                    "SCX_LOGIN_APPLICATION_GROUP: requested GID (0x%x) "
                    "does not match real eGID (0x%x)"
                    "or any of the supplementary GIDs\n",
                    pConn, nRequestedGID, current_egid());
            nError = -EACCES;
            goto error;
        }

        nError = SCXLNXConnHashApplicationPathAndData(pSHA1Hash,
                 &nRequestedGID, sizeof(u32));
        if (nError != 0) {
            dprintk(KERN_ERR "SCXLNXConnOpenClientSession: "
                    "error in SCXLNXConnHashApplicationPath"
                    "AndData\n");
            goto error;
        }

        memcpy(&pMessage->sOpenClientSessionMessage.sLoginData,
               pSHA1Hash, 16);
        pMessage->sOpenClientSessionMessage.nLoginType =
            SCX_LOGIN_APPLICATION_GROUP_LINUX_PATH_GID_SHA1_HASH;

        /* 16 bytes */
        pMessage->sOpenClientSessionMessage.nMessageSize += 4;
        break;
    }
#else
    case SCX_LOGIN_APPLICATION_GROUP: {
        /*
         * Check requested GID. Send the real UID and the requested GID
         * in the login data. Update message size.
         */
        gid_t nRequestedGID;

        nRequestedGID =	*(u32 *) &pMessage->sOpenClientSessionMessage.
                        sLoginData;

        if (!SCXLNXConnCheckGID(nRequestedGID)) {
            dprintk(KERN_ERR "SCXLNXConnOpenClientSession(%p) "
                    "SCX_LOGIN_APPLICATION_GROUP: requested GID (0x%x) "
                    "does not match real eGID (0x%x)"
                    "or any of the supplementary GIDs\n",
                    pConn, nRequestedGID, current_egid());
            nError = -EACCES;
            goto error;
        }

        *(u32 *) &pMessage->sOpenClientSessionMessage.sLoginData =
            current_uid();
        *(u32 *) &pMessage->sOpenClientSessionMessage.sLoginData[4] =
            nRequestedGID;

        pMessage->sOpenClientSessionMessage.nLoginType =
            SCX_LOGIN_APPLICATION_GROUP_ANDROID_UID_GID;

        /* Added two words */
        pMessage->sOpenClientSessionMessage.nMessageSize += 2;

        break;
    }
#endif

    case SCX_LOGIN_PRIVILEGED:
        /*
         * Check that calling application either hash EUID=0 or has
         * EGID=0
         */
        if (current_euid() != 0 && current_egid() != 0) {
            dprintk(KERN_ERR "SCXLNXConnOpenClientSession: "
                    " user %d, group %d not allowed to open "
                    "session with SCX_LOGIN_PRIVILEGED\n",
                    current_euid(), current_egid());
            nError = -EACCES;
            goto error;
        }
        pMessage->sOpenClientSessionMessage.nLoginType =
            SCX_LOGIN_PRIVILEGED;
        break;

    case SCX_LOGIN_AUTHENTICATION: {
        /*
         * Compute SHA-1 hash of the application binary
         * Send this hash as the login data (20 bytes)
         */

        u8 *pHash;
        pHash = &(pMessage->sOpenClientSessionMessage.sLoginData[0]);

        nError = SCXLNXConnGetCurrentProcessHash(pHash);
        if (nError != 0) {
            dprintk(KERN_ERR "SCXLNXConnOpenClientSession: "
                    "error in SCXLNXConnGetCurrentProcessHash\n");
            goto error;
        }
        pMessage->sOpenClientSessionMessage.nLoginType =
            SCX_LOGIN_AUTHENTICATION_BINARY_SHA1_HASH;

        /* 20 bytes */
        pMessage->sOpenClientSessionMessage.nMessageSize += 5;
        break;
    }

    default:
        dprintk(KERN_ERR "SCXLNXConnOpenClientSession: "
                "unknown nLoginType(%08X)\n",
                pMessage->sOpenClientSessionMessage.nLoginType);
        nError = -EOPNOTSUPP;
        goto error;
    }

    /* Map the temporary memory references */
    for (i = 0; i < 4; i++) {
        int nParamType;
        nParamType = SCX_GET_PARAM_TYPE(
                         pMessage->sOpenClientSessionMessage.nParamTypes, i);
        if ((nParamType & (SCX_PARAM_TYPE_MEMREF_FLAG |
                           SCX_PARAM_TYPE_REGISTERED_MEMREF_FLAG))
                == SCX_PARAM_TYPE_MEMREF_FLAG) {
            /* Map temp mem ref */
            nError = SCXLNXConnMapTempShMem(pConn,
                                            &pMessage->sOpenClientSessionMessage.
                                            sParams[i].sTempMemref,
                                            nParamType,
                                            &pShmemDesc[i]);
            if (nError != 0) {
                dprintk(KERN_ERR "SCXLNXConnOpenClientSession: "
                        "unable to map temporary memory block "
                        "(%08X)\n", nError);
                goto error;
            }
        }
    }

    /* Fill the handle of the Device Context */
    pMessage->sOpenClientSessionMessage.hDeviceContext =
        pConn->hDeviceContext;

    nError = SCXLNXCommSendReceive(
                 &pConn->pDevice->sm,
                 pMessage,
                 pAnswer,
                 pConn,
                 true);

error:
    /* Unmap the temporary memory references */
    for (i = 0; i < 4; i++)
        if (pShmemDesc[i] != NULL)
            SCXLNXConnUnmapShmem(pConn, pShmemDesc[i], 0);

    if (nError != 0)
        dprintk(KERN_ERR "SCXLNXConnOpenClientSession returns %d\n",
                nError);
    else
        dprintk(KERN_ERR "SCXLNXConnOpenClientSession returns "
                "nErrorCode 0x%08X\n",
                pAnswer->sOpenClientSessionAnswer.nErrorCode);

    return nError;
}
Пример #6
0
/*
 * Opens a client session to the Secure World
 */
int tf_open_client_session(
	struct tf_connection *connection,
	union tf_command *command,
	union tf_answer *answer)
{
	int error = 0;
	struct tf_shmem_desc *shmem_desc[4] = {NULL};
	u32 i;

	dprintk(KERN_INFO "tf_open_client_session(%p)\n", connection);

	/*
	 * Initialize the message size with no login data. This will be later
	 * adjusted the the cases below
	 */
	command->open_client_session.message_size =
		(sizeof(struct tf_command_open_client_session) - 20
			- sizeof(struct tf_command_header))/4;

	switch (command->open_client_session.login_type) {
	case TF_LOGIN_PUBLIC:
		 /* Nothing to do */
		 break;

	case TF_LOGIN_USER:
		/*
		 * Send the EUID of the calling application in the login data.
		 * Update message size.
		 */
		*(u32 *) &command->open_client_session.login_data =
			current_euid();
#ifndef CONFIG_ANDROID
		command->open_client_session.login_type =
			(u32) TF_LOGIN_USER_LINUX_EUID;
#else
		command->open_client_session.login_type =
			(u32) TF_LOGIN_USER_ANDROID_EUID;
#endif

		/* Added one word */
		command->open_client_session.message_size += 1;
		break;

	case TF_LOGIN_GROUP: {
		/* Check requested GID */
		gid_t  requested_gid =
			*(u32 *) command->open_client_session.login_data;

		if (!tf_check_gid(requested_gid)) {
			dprintk(KERN_ERR "tf_open_client_session(%p) "
				"TF_LOGIN_GROUP: requested GID (0x%x) does "
				"not match real eGID (0x%x)"
				"or any of the supplementary GIDs\n",
				connection, requested_gid, current_egid());
			error = -EACCES;
			goto error;
		}
#ifndef CONFIG_ANDROID
		command->open_client_session.login_type =
			TF_LOGIN_GROUP_LINUX_GID;
#else
		command->open_client_session.login_type =
			TF_LOGIN_GROUP_ANDROID_GID;
#endif

		command->open_client_session.message_size += 1; /* GID */
		break;
	}

#ifndef CONFIG_ANDROID
	case TF_LOGIN_APPLICATION: {
		/*
		 * Compute SHA-1 hash of the application fully-qualified path
		 * name.  Truncate the hash to 16 bytes and send it as login
		 * data.  Update message size.
		 */
		u8 pSHA1Hash[SHA1_DIGEST_SIZE];

		error = tf_hash_application_path_and_data(pSHA1Hash,
			NULL, 0);
		if (error != 0) {
			dprintk(KERN_ERR "tf_open_client_session: "
				"error in tf_hash_application_path_and_data\n");
			goto error;
		}
		memcpy(&command->open_client_session.login_data,
			pSHA1Hash, 16);
		command->open_client_session.login_type =
			TF_LOGIN_APPLICATION_LINUX_PATH_SHA1_HASH;
		/* 16 bytes */
		command->open_client_session.message_size += 4;
		break;
	}
#else
	case TF_LOGIN_APPLICATION:
		/*
		 * Send the real UID of the calling application in the login
		 * data. Update message size.
		 */
		*(u32 *) &command->open_client_session.login_data =
			current_uid();

		command->open_client_session.login_type =
			(u32) TF_LOGIN_APPLICATION_ANDROID_UID;

		/* Added one word */
		command->open_client_session.message_size += 1;
		break;
#endif

#ifndef CONFIG_ANDROID
	case TF_LOGIN_APPLICATION_USER: {
		/*
		 * Compute SHA-1 hash of the concatenation of the application
		 * fully-qualified path name and the EUID of the calling
		 * application.  Truncate the hash to 16 bytes and send it as
		 * login data.  Update message size.
		 */
		u8 pSHA1Hash[SHA1_DIGEST_SIZE];

		error = tf_hash_application_path_and_data(pSHA1Hash,
			(u8 *) &(current_euid()), sizeof(current_euid()));
		if (error != 0) {
			dprintk(KERN_ERR "tf_open_client_session: "
				"error in tf_hash_application_path_and_data\n");
			goto error;
		}
		memcpy(&command->open_client_session.login_data,
			pSHA1Hash, 16);
		command->open_client_session.login_type =
			TF_LOGIN_APPLICATION_USER_LINUX_PATH_EUID_SHA1_HASH;

		/* 16 bytes */
		command->open_client_session.message_size += 4;

		break;
	}
#else
	case TF_LOGIN_APPLICATION_USER:
		/*
		 * Send the real UID and the EUID of the calling application in
		 * the login data. Update message size.
		 */
		*(u32 *) &command->open_client_session.login_data =
			current_uid();
		*(u32 *) &command->open_client_session.login_data[4] =
			current_euid();

		command->open_client_session.login_type =
			TF_LOGIN_APPLICATION_USER_ANDROID_UID_EUID;

		/* Added two words */
		command->open_client_session.message_size += 2;
		break;
#endif

#ifndef CONFIG_ANDROID
	case TF_LOGIN_APPLICATION_GROUP: {
		/*
		 * Check requested GID.  Compute SHA-1 hash of the concatenation
		 * of the application fully-qualified path name and the
		 * requested GID.  Update message size
		 */
		gid_t  requested_gid;
		u8     pSHA1Hash[SHA1_DIGEST_SIZE];

		requested_gid =	*(u32 *) &command->open_client_session.
			login_data;

		if (!tf_check_gid(requested_gid)) {
			dprintk(KERN_ERR "tf_open_client_session(%p) "
			"TF_LOGIN_APPLICATION_GROUP: requested GID (0x%x) "
			"does not match real eGID (0x%x)"
			"or any of the supplementary GIDs\n",
			connection, requested_gid, current_egid());
			error = -EACCES;
			goto error;
		}

		error = tf_hash_application_path_and_data(pSHA1Hash,
			&requested_gid, sizeof(u32));
		if (error != 0) {
			dprintk(KERN_ERR "tf_open_client_session: "
				"error in tf_hash_application_path_and_data\n");
			goto error;
		}

		memcpy(&command->open_client_session.login_data,
			pSHA1Hash, 16);
		command->open_client_session.login_type =
			TF_LOGIN_APPLICATION_GROUP_LINUX_PATH_GID_SHA1_HASH;

		/* 16 bytes */
		command->open_client_session.message_size += 4;
		break;
	}
#else
	case TF_LOGIN_APPLICATION_GROUP: {
		/*
		 * Check requested GID. Send the real UID and the requested GID
		 * in the login data. Update message size.
		 */
		gid_t requested_gid;

		requested_gid =	*(u32 *) &command->open_client_session.
			login_data;

		if (!tf_check_gid(requested_gid)) {
			dprintk(KERN_ERR "tf_open_client_session(%p) "
			"TF_LOGIN_APPLICATION_GROUP: requested GID (0x%x) "
			"does not match real eGID (0x%x)"
			"or any of the supplementary GIDs\n",
			connection, requested_gid, current_egid());
			error = -EACCES;
			goto error;
		}

		*(u32 *) &command->open_client_session.login_data =
			current_uid();
		*(u32 *) &command->open_client_session.login_data[4] =
			requested_gid;

		command->open_client_session.login_type =
			TF_LOGIN_APPLICATION_GROUP_ANDROID_UID_GID;

		/* Added two words */
		command->open_client_session.message_size += 2;

		break;
	}
#endif

	case TF_LOGIN_PRIVILEGED:
		/* A privileged login may be performed only on behalf of the
		   kernel itself or on behalf of a process with euid=0 or
		   egid=0 or euid=system or egid=system. */
		if (connection->owner == TF_CONNECTION_OWNER_KERNEL) {
			dprintk(KERN_DEBUG "tf_open_client_session: "
				"TF_LOGIN_PRIVILEGED for kernel API\n");
		} else if ((current_euid() != TF_PRIVILEGED_UID_GID) &&
			   (current_egid() != TF_PRIVILEGED_UID_GID) &&
			   (current_euid() != 0) && (current_egid() != 0)) {
			dprintk(KERN_ERR "tf_open_client_session: "
				" user %d, group %d not allowed to open "
				"session with TF_LOGIN_PRIVILEGED\n",
				current_euid(), current_egid());
			error = -EACCES;
			goto error;
		} else {
			dprintk(KERN_DEBUG "tf_open_client_session: "
				"TF_LOGIN_PRIVILEGED for %u:%u\n",
				current_euid(), current_egid());
		}
		command->open_client_session.login_type =
			TF_LOGIN_PRIVILEGED;
		break;

	case TF_LOGIN_AUTHENTICATION: {
		/*
		 * Compute SHA-1 hash of the application binary
		 * Send this hash as the login data (20 bytes)
		 */

		u8 *hash;
		hash = &(command->open_client_session.login_data[0]);

		error = tf_get_current_process_hash(hash);
		if (error != 0) {
			dprintk(KERN_ERR "tf_open_client_session: "
				"error in tf_get_current_process_hash\n");
			goto error;
		}
		command->open_client_session.login_type =
			TF_LOGIN_AUTHENTICATION_BINARY_SHA1_HASH;

		/* 20 bytes */
		command->open_client_session.message_size += 5;
		break;
	}

	case TF_LOGIN_PRIVILEGED_KERNEL:
		/* A kernel login may be performed only on behalf of the
		   kernel itself. */
		if (connection->owner == TF_CONNECTION_OWNER_KERNEL) {
			dprintk(KERN_DEBUG "tf_open_client_session: "
				"TF_LOGIN_PRIVILEGED_KERNEL for kernel API\n");
			command->open_client_session.login_type =
				TF_LOGIN_PRIVILEGED_KERNEL;
		} else {
			dprintk(KERN_ERR "tf_open_client_session: "
				" user %d, group %d not allowed to open "
				"session with TF_LOGIN_PRIVILEGED_KERNEL\n",
				current_euid(), current_egid());
			error = -EACCES;
			goto error;
		}
		command->open_client_session.login_type =
			TF_LOGIN_PRIVILEGED_KERNEL;
		break;

	default:
		 dprintk(KERN_ERR "tf_open_client_session: "
			"unknown login_type(%08X)\n",
			command->open_client_session.login_type);
		 error = -EOPNOTSUPP;
		 goto error;
	}

	/* Map the temporary memory references */
	for (i = 0; i < 4; i++) {
		int param_type;
		param_type = TF_GET_PARAM_TYPE(
			command->open_client_session.param_types, i);
		if ((param_type & (TF_PARAM_TYPE_MEMREF_FLAG |
				   TF_PARAM_TYPE_REGISTERED_MEMREF_FLAG))
				== TF_PARAM_TYPE_MEMREF_FLAG) {
			/* Map temp mem ref */
			error = tf_map_temp_shmem(connection,
				&command->open_client_session.
					params[i].temp_memref,
				param_type,
				&shmem_desc[i]);
			if (error != 0) {
				dprintk(KERN_ERR "tf_open_client_session: "
					"unable to map temporary memory block "
					"(%08X)\n", error);
				goto error;
			}
		}
	}

	/* Fill the handle of the Device Context */
	command->open_client_session.device_context =
		connection->device_context;

	error = tf_send_receive(
		&connection->dev->sm,
		command,
		answer,
		connection,
		true);

error:
	/* Unmap the temporary memory references */
	for (i = 0; i < 4; i++)
		if (shmem_desc[i] != NULL)
			tf_unmap_shmem(connection, shmem_desc[i], 0);

	if (error != 0)
		dprintk(KERN_ERR "tf_open_client_session returns %d\n",
			error);
	else
		dprintk(KERN_ERR "tf_open_client_session returns "
			"error_code 0x%08X\n",
			answer->open_client_session.error_code);

	return error;
}