Care should be taken to ensure that the proper execution of a module is not compromised by a lack of system resources. If a module is unable to open sufficient files to perform its task, it should fail gracefully, or request additional resources. Specifically, the quantities manipulated by the setrlimit(2) family of commands should be taken into consideration.
          Generally, the module may wish to establish the identity of
          the user requesting a service. This may not be the same as
          the username returned by pam_get_user().
          Indeed, that is only going to be the name of the user under
          whose identity the service will be given. This is not
          necessarily the user that requests the service.
        
In other words, user X runs a program that is setuid-Y, it grants the user to have the permissions of Z. A specific example of this sort of service request is the su program: user joe executes su to become the user jane. In this situation X=joe, Y=root and Z=jane. Clearly, it is important that the module does not confuse these different users and grant an inappropriate level of privilege.
The following is the convention to be adhered to when juggling user-identities.
- X, the identity of the user invoking the service request. This is the user identifier; returned by the function getuid(2). 
- Y, the privileged identity of the application used to grant the requested service. This is the effective user identifier; returned by the function geteuid(2). 
- Z, the user under whose identity the service will be granted. This is the username returned by - pam_get_user()and also stored in the Linux-PAM item, PAM_USER.
- Linux-PAM has a place for an additional user identity that a module may care to make use of. This is the PAM_RUSER item. Generally, network sensitive modules/applications may wish to set/read this item to establish the identity of the user requesting a service from a remote location. 
Note, if a module wishes to modify the identity of either the uid or euid of the running process, it should take care to restore the original values prior to returning control to the Linux-PAM library.
Prior to calling the conversation function, the module should reset the contents of the pointer that will return the applications response. This is a good idea since the application may fail to fill the pointer and the module should be in a position to notice!
The module should be prepared for a failure from the conversation. The generic error would be PAM_CONV_ERR, but anything other than PAM_SUCCESS should be treated as indicating failure.
          To ensure that the authentication tokens are not left lying
          around the items, PAM_AUTHTOK and
          PAM_OLDAUTHTOK, are not available to
          the application: they are defined in
          <security/pam_modules.h>. This
          is ostensibly for security reasons, but a maliciously
          programmed application will always have access to all memory
          of the process, so it is only superficially enforced. As a
          general rule the module should overwrite authentication tokens
          as soon as they are no longer needed. Especially before
          free()'ing them. The
          Linux-PAM library is
          required to do this when either of these authentication
          token items are (re)set.
        
          Not to dwell too little on this concern; should the module
          store the authentication tokens either as (automatic) function
          variables or using pam_[gs]et_data() the
          associated memory should be over-written explicitly before it
          is released. In the case of the latter storage mechanism, the
          associated cleanup() function should
          explicitly overwrite the *data before
          free()'ing it: for example,
          
/*
 * An example cleanup() function for releasing memory that was used to
 * store a password.
 */
int cleanup(pam_handle_t *pamh, void *data, int error_status)
{
    char *xx;
    if ((xx = data)) {
        while (*xx)
            *xx++ = '\0';
        free(data);
    }
    return PAM_SUCCESS;
}