Changeset 255


Ignore:
Timestamp:
Jun 5, 2009, 10:05:48 AM (16 years ago)
Author:
Herwig Bauernfeind
Message:

os2_randget() fix for SIGSEGV with GCC 4.3.2 and -O2 in 3.3 branch

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified branches/samba-3.3.x/source/lib/os2ea.c

    r206 r255  
    3131#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
    3232#define CMD_KI_RDCNT            (0x63)
    33 
    34 typedef struct _CPUUTIL {
    35     ULONG ulTimeLow;     /* Low 32 bits of time stamp      */
    36     ULONG ulTimeHigh;    /* High 32 bits of time stamp     */
    37     ULONG ulIdleLow;     /* Low 32 bits of idle time       */
    38     ULONG ulIdleHigh;    /* High 32 bits of idle time      */
    39     ULONG ulBusyLow;     /* Low 32 bits of busy time       */
    40     ULONG ulBusyHigh;    /* High 32 bits of busy time      */
    41     ULONG ulIntrLow;     /* Low 32 bits of interrupt time  */
    42     ULONG ulIntrHigh;    /* High 32 bits of interrupt time */
    43    } CPUUTIL;
    4433
    4534#include "local.h"
     
    10998}
    11099
    111 // very simple random data gatherer derived from openssl
     100/* Functions below are based on APR random code */
     101/* Licensed to the Apache Software Foundation (ASF) under one or more
     102 * contributor license agreements.  See the NOTICE file distributed with
     103 * this work for additional information regarding copyright ownership.
     104 * The ASF licenses this file to You under the Apache License, Version 2.0
     105 * (the "License"); you may not use this file except in compliance with
     106 * the License.  You may obtain a copy of the License at
     107 *
     108 *     http://www.apache.org/licenses/LICENSE-2.0
     109 *
     110 * Unless required by applicable law or agreed to in writing, software
     111 * distributed under the License is distributed on an "AS IS" BASIS,
     112 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     113 * See the License for the specific language governing permissions and
     114 * limitations under the License.
     115 */
     116
    112117void os2_randget(char * buffer, int length)
    113118{
    114         QWORD qwTime;
    115         ULONG SysVars[QSV_FOREGROUND_PROCESS];
    116         int done = 0;
    117 
    118         if (!buffer || length <= 0)
    119         {
    120                 return;
    121         }
    122 
    123         DosTmrQueryTime(&qwTime);
    124         memcpy(buffer, &qwTime, sizeof(qwTime) > length ? length : sizeof(qwTime));
    125         done += sizeof(qwTime);
    126         if (done >= length)
    127         {
    128                 return;
    129         }
    130 
    131         if (DosPerfSysCall)
    132         {
    133                 CPUUTIL util;
    134                 if (DosPerfSysCall(CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0)
    135                 {
    136                         memcpy(buffer + done, &util, sizeof(util) > length - done ? length - done : sizeof(util));
    137                         done += sizeof(util);
    138                         if (done >= length)
    139                         {
    140                                 return;
    141                         }
    142                 }
    143         }
    144 
    145         DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars));
    146         memcpy(buffer + done, SysVars, sizeof(SysVars) > length - done ? length - done : sizeof(SysVars));
     119    UCHAR randbyte();
     120    unsigned int idx;
     121
     122    for (idx=0; idx<length; idx++)
     123        buffer[idx] = randbyte();
     124
     125}
     126
     127/* A bunch of system information like memory & process stats.
     128 * Not highly random but every bit helps....
     129 */
     130static UCHAR randbyte_sysinfo()
     131{
     132    UCHAR byte = 0;
     133    UCHAR SysVars[100];
     134    int b;
     135
     136    DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars));
     137
     138    for (b = 0; b < 100; b++) {
     139        byte ^= SysVars[b];
     140    }
     141
     142    return byte;
     143}
     144
     145
     146
     147/* Similar in concept to randbyte_hrtimer() but accesses the CPU's internal
     148 * counters which run at the CPU's MHz speed. We get separate
     149 * idle / busy / interrupt cycle counts which should provide very good
     150 * randomness due to interference of hardware events.
     151 * This only works on newer CPUs (at least PPro or K6) and newer OS/2 versions
     152 * which is why it's run-time linked.
     153 */
     154
     155static HMODULE hDoscalls = 0;
     156#define   CMD_KI_RDCNT    (0x63)
     157
     158typedef struct _CPUUTIL {
     159    ULONG ulTimeLow;            /* Low 32 bits of time stamp      */
     160    ULONG ulTimeHigh;           /* High 32 bits of time stamp     */
     161    ULONG ulIdleLow;            /* Low 32 bits of idle time       */
     162    ULONG ulIdleHigh;           /* High 32 bits of idle time      */
     163    ULONG ulBusyLow;            /* Low 32 bits of busy time       */
     164    ULONG ulBusyHigh;           /* High 32 bits of busy time      */
     165    ULONG ulIntrLow;            /* Low 32 bits of interrupt time  */
     166    ULONG ulIntrHigh;           /* High 32 bits of interrupt time */
     167} CPUUTIL;
     168
     169
     170static UCHAR randbyte_perf()
     171{
     172    UCHAR byte = 0;
     173    CPUUTIL util;
     174    int c;
     175
     176#ifndef __INNOTEK_LIBC__
     177    if (hDoscalls == 0) {
     178        char failed_module[20];
     179        ULONG rc;
     180
     181        rc = DosLoadModule(failed_module, sizeof(failed_module), "DOSCALLS",
     182                           &hDoscalls);
     183
     184        if (rc == 0) {
     185            rc = DosQueryProcAddr(hDoscalls, 976, NULL, (PFN *)&DosPerfSysCall);
     186
     187            if (rc) {
     188                DosPerfSysCall = NULL;
     189            }
     190        }
     191    }
     192
     193    if (DosPerfSysCall) {
     194        if (DosPerfSysCall(CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0) {
     195            for (c = 0; c < sizeof(util); c++) {
     196                byte ^= ((UCHAR *)&util)[c];
     197            }
     198        }
     199        else {
     200            DosPerfSysCall = NULL;
     201        }
     202    }
     203#endif
     204    return byte;
     205}
     206
     207
     208
     209UCHAR randbyte()
     210{
     211    return randbyte_sysinfo() ^ randbyte_perf();
    147212}
    148213
Note: See TracChangeset for help on using the changeset viewer.